@epoch-agent/core 0.30.0 → 1.1.0

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.d.ts CHANGED
@@ -7265,13 +7265,17 @@ declare function loadPlugins(opts: PluginLoadOptions): PluginArtifacts;
7265
7265
  * | 族 | 谁读它 |
7266
7266
  * | ----------------------------------------------- | ---------------------------------------- |
7267
7267
  * | `name` / `version` / `epochVersion` / `author` | **epoch 自己** —— 装不装得上、叫什么 |
7268
- * | `displayName` / `category` / `visibility` / `changelog` | **上传那一屏的预填**,epoch 一个字不读 |
7268
+ * | `displayName` / `category` / `visibility` / `changelog` | **上传那一屏的预填**(`displayName` 例外,见下) |
7269
7269
  * | `description` / `homepage` / `keywords` / `icon` | 两边都读(`icon` 见它那一格) |
7270
7270
  * | `dependencies` | **epoch 自己** —— 装它时要一起装谁 |
7271
7271
  *
7272
7272
  * 第二族 2026-09-15 加的,判据在它们自己那几格上。要紧的一条:它们是**预填**,
7273
7273
  * 用户在那一屏上改得动,改了之后发出去的是改后的 —— 包里这一份原地不动。
7274
7274
  *
7275
+ * ⚠️ **`displayName` 不只是预填**(这张表原来写的「epoch 一个字不读」早就不成立了):
7276
+ * 安装前那一屏预览和依赖清单读它(`install.ts`),已装那一栏在市场目录说不出名字时
7277
+ * 也拿它兜底(2026-10-14,runtime 的 `PluginEntryView.packageDisplayName`)。
7278
+ *
7275
7279
  * 文件名放在**插件根**,不学竞品的 `.claude-plugin/` 子目录 —— 多一层目录没带来
7276
7280
  * 任何好处,而「插件根下有没有 `epoch-plugin.json`」是判定「这是不是一个插件」
7277
7281
  * 最省事的问法。
@@ -12332,11 +12336,15 @@ declare const EpochConfigSchema: z.ZodObject<{
12332
12336
  }, z.core.$strip>>;
12333
12337
  }, z.core.$strip>>;
12334
12338
  brand: z.ZodOptional<z.ZodString>;
12339
+ brandWhenSidebarCollapsed: z.ZodOptional<z.ZodEnum<{
12340
+ hide: "hide";
12341
+ show: "show";
12342
+ }>>;
12335
12343
  sidebarMenu: z.ZodOptional<z.ZodArray<z.ZodObject<{
12336
12344
  id: z.ZodString;
12337
12345
  label: z.ZodString;
12338
12346
  icon: z.ZodOptional<z.ZodString>;
12339
- pinned: z.ZodOptional<z.ZodBoolean>;
12347
+ primary: z.ZodOptional<z.ZodBoolean>;
12340
12348
  }, z.core.$strip>>>;
12341
12349
  userMenu: z.ZodOptional<z.ZodArray<z.ZodObject<{
12342
12350
  id: z.ZodString;
@@ -15527,6 +15535,12 @@ interface StoredAppearance {
15527
15535
  theme?: string;
15528
15536
  /** 语言偏好(`system | zh | en`)。缺席 = 没选过 */
15529
15537
  lang?: string;
15538
+ /**
15539
+ * 宽屏侧栏宽度(px,2026-10-14 侧栏可拖之后)。缺席 = 没拖过。
15540
+ * 同上面两格:这一层**只判结构**(正整数),上下限归 protocol 的
15541
+ * `isAppearanceSidebarWidth`,由写入口和首屏那段脚本各自把关 —— 盘上一个越界的数是惰性的
15542
+ */
15543
+ sidebarWidth?: number;
15530
15544
  }
15531
15545
  declare class AppearanceStore {
15532
15546
  private readonly filePath;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { PROVIDER_TYPES, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, isSettingsPaneId, SETTINGS_PANE_IDS, PERMISSION_LEVELS, SHELL_KINDS, cronTimes, SCHEDULE_MAX_TIMES_PER_DAY, SCHEDULE_INTERVAL_MIN_MINUTES, SCHEDULE_INTERVAL_MAX_MINUTES, ToolExposure, MAX_OPTIONS, MIN_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, isPermissionLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, parseModelRef, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, NOOP_TELEMETRY, METRIC, contentToText, GEN_AI, isPromptOversize, promptTokens, apiKeyEnvVar, PROVIDER_INFOS, isProviderType, API_KEY_ENV_VARS, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, imagePartOmittedSummary, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
1
+ import { PROVIDER_TYPES, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, isSettingsPaneId, SETTINGS_PANE_IDS, BRAND_WHEN_SIDEBAR_COLLAPSED, PERMISSION_LEVELS, SHELL_KINDS, cronTimes, SCHEDULE_MAX_TIMES_PER_DAY, SCHEDULE_INTERVAL_MIN_MINUTES, SCHEDULE_INTERVAL_MAX_MINUTES, ToolExposure, MAX_OPTIONS, MIN_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, isPermissionLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, parseModelRef, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, NOOP_TELEMETRY, METRIC, contentToText, GEN_AI, isPromptOversize, promptTokens, apiKeyEnvVar, PROVIDER_INFOS, isProviderType, API_KEY_ENV_VARS, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, imagePartOmittedSummary, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
2
2
  export { API_KEY_ENV_VARS, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, MAX_ATTACH_BYTES, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_ATTACH_BYTES, MAX_SESSION_REFS, OPERATION_TYPES, PERMISSION_LEVELS, PLAN_OUTCOMES, PROVIDER_INFOS, PROVIDER_TYPES, ToolExposure, apiKeyEnvVar, extractAllMentions, extractMentions, extractSessionMentions, getProviderInfo, isOperationType, isPermissionLevel, isPlanOutcome, isProviderType, normalizeApproval } from '@epoch-agent/protocol';
3
3
  import { existsSync, statSync, readdirSync, readFileSync, mkdirSync, writeFileSync, rmSync, renameSync, realpathSync, symlinkSync, cpSync, lstatSync, unlinkSync, rmdirSync, mkdtempSync, copyFileSync, openSync, writeSync, closeSync, readSync } from 'fs';
4
4
  import { homedir, platform, tmpdir, hostname } from 'os';
@@ -1568,7 +1568,7 @@ async function* runTurnStreaming(opts) {
1568
1568
  if (chunk.warnings) warnings = chunk.warnings;
1569
1569
  break;
1570
1570
  case "error":
1571
- streamError = chunk.error ?? t("agent_run.unknown_provider_error");
1571
+ streamError = chunk.error || t("provider_route.no_detail");
1572
1572
  break;
1573
1573
  case "tool-result":
1574
1574
  break;
@@ -8953,14 +8953,28 @@ function describeBackgroundTask(task) {
8953
8953
  }
8954
8954
  var HEAVY_SOURCE_RATIO = 0.15;
8955
8955
  var HEAVY_SKILL_RATIO = 0.02;
8956
- function seg(label, text, detail) {
8957
- const tokens = text ? estimateTokens(text) : 0;
8958
- if (tokens === 0) return null;
8959
- return { label, tokens, ...detail ? { detail } : {} };
8956
+ var SEG_KEY = {
8957
+ system: "context_breakdown.seg_system",
8958
+ instructions: "context_breakdown.seg_instructions",
8959
+ tools: "context_breakdown.seg_tools",
8960
+ skills: "context_breakdown.seg_skills",
8961
+ memory: "context_breakdown.seg_memory",
8962
+ history: "context_breakdown.seg_history"
8963
+ };
8964
+ var NOTE_KEY = {
8965
+ heavy_mcp: "context_breakdown.heavy_mcp",
8966
+ heavy_tools: "context_breakdown.heavy_tools",
8967
+ heavy_skills: "context_breakdown.heavy_skills",
8968
+ heavy_skills_owner: "context_breakdown.heavy_skills_owner",
8969
+ skills_capped: "context_breakdown.skills_capped",
8970
+ near_limit: "context_breakdown.near_limit"
8971
+ };
8972
+ function seg(kind, text, detail) {
8973
+ return segOf(kind, text ? estimateTokens(text) : 0, detail);
8960
8974
  }
8961
- function segOf(label, tokens, detail) {
8975
+ function segOf(kind, tokens, detail, extra) {
8962
8976
  if (tokens === 0) return null;
8963
- return { label, tokens, ...detail ? { detail } : {} };
8977
+ return { label: t(SEG_KEY[kind]), tokens, kind, ...detail ? { detail } : {}, ...extra };
8964
8978
  }
8965
8979
  function toolDetail(input, toolTokens) {
8966
8980
  const bySource = /* @__PURE__ */ new Map();
@@ -8971,93 +8985,80 @@ function toolDetail(input, toolTokens) {
8971
8985
  bySource.set(source, entry);
8972
8986
  }
8973
8987
  const mcp = [...bySource.entries()].filter(([source]) => source.startsWith("mcp:"));
8974
- const localCount = input.tools.length - mcp.reduce((n, [, e]) => n + e.count, 0);
8975
- const detail = mcp.length > 0 ? t("context_breakdown.tools_mixed", {
8976
- local: localCount,
8977
- mcp: mcp.reduce((n, [, e]) => n + e.count, 0)
8978
- }) : t("context_breakdown.tools_local_only", { local: localCount });
8979
- const hints = [];
8988
+ const mcpCount = mcp.reduce((n, [, e]) => n + e.count, 0);
8989
+ const localCount = input.tools.length - mcpCount;
8990
+ const detail = mcp.length > 0 ? t("context_breakdown.tools_mixed", { local: localCount, mcp: mcpCount }) : t("context_breakdown.tools_local_only", { local: localCount });
8991
+ const notes = [];
8980
8992
  if (input.limit > 0) {
8981
8993
  for (const [source, entry] of mcp) {
8982
8994
  const ratio = entry.tokens / input.limit;
8983
8995
  if (ratio < HEAVY_SOURCE_RATIO) continue;
8984
8996
  const server = source.slice("mcp:".length);
8985
- hints.push(
8986
- t("context_breakdown.heavy_mcp", {
8997
+ notes.push({
8998
+ code: "heavy_mcp",
8999
+ params: {
8987
9000
  server,
8988
9001
  count: entry.count,
8989
9002
  percent: Math.round(ratio * 100),
8990
9003
  tokens: Math.round(entry.tokens / 100) / 10
8991
- })
8992
- );
9004
+ }
9005
+ });
8993
9006
  }
8994
9007
  }
8995
- if (input.limit > 0 && toolTokens / input.limit > 0.3 && hints.length === 0) {
8996
- hints.push(
8997
- t("context_breakdown.heavy_tools", {
8998
- percent: Math.round(toolTokens / input.limit * 100)
8999
- })
9000
- );
9008
+ if (input.limit > 0 && toolTokens / input.limit > 0.3 && notes.length === 0) {
9009
+ notes.push({
9010
+ code: "heavy_tools",
9011
+ params: { percent: Math.round(toolTokens / input.limit * 100) }
9012
+ });
9001
9013
  }
9002
- return { detail, hints };
9014
+ return { detail, counts: { local: localCount, mcp: mcpCount }, notes };
9003
9015
  }
9004
- function skillHints(input, skillTokens) {
9016
+ function skillNotes(input, skillTokens) {
9005
9017
  const stats = input.skillIndex;
9006
9018
  if (!stats || stats.total === 0 || skillTokens === 0) return [];
9007
9019
  if (stats.dropped > 0) {
9008
- return [
9009
- t("context_breakdown.skills_capped", {
9010
- indexed: stats.indexed,
9011
- dropped: stats.dropped
9012
- })
9013
- ];
9020
+ return [{ code: "skills_capped", params: { indexed: stats.indexed, dropped: stats.dropped } }];
9014
9021
  }
9015
- const hints = [];
9022
+ const notes = [];
9016
9023
  if (input.limit > 0 && skillTokens / input.limit >= HEAVY_SKILL_RATIO) {
9017
- hints.push(
9018
- t("context_breakdown.heavy_skills", {
9024
+ notes.push({
9025
+ code: "heavy_skills",
9026
+ params: {
9019
9027
  count: stats.indexed,
9020
9028
  percent: Math.round(skillTokens / input.limit * 100)
9021
- })
9022
- );
9029
+ }
9030
+ });
9023
9031
  if (stats.heaviest) {
9024
- hints.push(
9025
- t("context_breakdown.heavy_skills_owner", {
9026
- owner: stats.heaviest.owner,
9027
- count: stats.heaviest.count
9028
- })
9029
- );
9032
+ notes.push({
9033
+ code: "heavy_skills_owner",
9034
+ params: { owner: stats.heaviest.owner, count: stats.heaviest.count }
9035
+ });
9030
9036
  }
9031
9037
  }
9032
- return hints;
9038
+ return notes;
9033
9039
  }
9034
9040
  function buildContextBreakdown(input) {
9035
9041
  const toolTokens = input.tools.reduce((sum, { tool }) => sum + toolDefinitionTokens(tool), 0);
9036
- const { detail, hints } = toolDetail(input, toolTokens);
9037
- const skillsSeg = seg(t("context_breakdown.seg_skills"), input.system.skills);
9042
+ const { detail, counts, notes } = toolDetail(input, toolTokens);
9043
+ const skillsSeg = seg("skills", input.system.skills);
9038
9044
  const segments = [
9039
- seg("system prompt", `${input.system.identity}
9045
+ seg("system", `${input.system.identity}
9040
9046
  ${input.system.head}
9041
9047
  ${input.system.rules}`),
9042
- seg(
9043
- t("context_breakdown.seg_instructions"),
9044
- input.projectBlock,
9045
- t("context_breakdown.seg_instructions_detail")
9046
- ),
9047
- segOf(t("context_breakdown.seg_tools"), toolTokens, detail),
9048
+ seg("instructions", input.projectBlock, t("context_breakdown.seg_instructions_detail")),
9049
+ segOf("tools", toolTokens, detail, { toolCounts: counts }),
9048
9050
  skillsSeg,
9049
- seg(t("context_breakdown.seg_memory"), input.memoryBlock),
9050
- seg(t("context_breakdown.seg_history"), input.historyText)
9051
+ seg("memory", input.memoryBlock),
9052
+ seg("history", input.historyText)
9051
9053
  ].filter((s) => s !== null);
9052
- hints.push(...skillHints(input, skillsSeg?.tokens ?? 0));
9054
+ notes.push(...skillNotes(input, skillsSeg?.tokens ?? 0));
9053
9055
  const used = segments.reduce((sum, s) => sum + s.tokens, 0);
9054
9056
  const remaining = input.limit > 0 ? Math.max(0, input.limit - used) : 0;
9055
9057
  if (input.limit > 0 && used / input.limit > 0.8) {
9056
- hints.push(
9057
- t("context_breakdown.near_limit", { percent: Math.round(used / input.limit * 100) })
9058
- );
9058
+ notes.push({ code: "near_limit", params: { percent: Math.round(used / input.limit * 100) } });
9059
9059
  }
9060
- return { limit: input.limit, used, remaining, segments, hints };
9060
+ const hints = notes.map((note) => t(NOTE_KEY[note.code], note.params));
9061
+ return { limit: input.limit, used, remaining, segments, hints, notes };
9061
9062
  }
9062
9063
  // src/cost/display.ts
9063
9064
  var currency;
@@ -10738,8 +10739,12 @@ var NETWORK_MESSAGE_RE = /timeout|timed.?out|etimedout|econnreset|enotfound|sock
10738
10739
  function describeProviderError(err) {
10739
10740
  const chain = causeChain(err);
10740
10741
  const head = chain[0]?.message ?? (typeof err === "string" ? err : String(err));
10741
- if (chain.length === 0) return head;
10742
10742
  const root = [...chain].reverse().find((link) => link.message !== "" && link.message !== head)?.message;
10743
+ if (!head.trim()) {
10744
+ if (root) return root;
10745
+ const status = extractStatus(err);
10746
+ return status === void 0 ? t("provider_route.no_detail") : t("provider_route.no_detail_status", { status });
10747
+ }
10743
10748
  return root ? t("provider_route.root_cause", { message: head, cause: root }) : head;
10744
10749
  }
10745
10750
  function extractStatus(err) {
@@ -13096,7 +13101,7 @@ var SidebarMenuItemSchema = z.object({
13096
13101
  icon: z.string().min(1).optional()
13097
13102
  });
13098
13103
  var SidebarNavItemSchema = SidebarMenuItemSchema.extend({
13099
- pinned: z.boolean().optional()
13104
+ primary: z.boolean().optional()
13100
13105
  });
13101
13106
  var BlankCardSchema = z.object({
13102
13107
  id: z.string().min(1),
@@ -13181,8 +13186,11 @@ var EpochConfigSchema = z.object({
13181
13186
  statusLine: StatusLineSchema.optional(),
13182
13187
  display: DisplaySchema2.optional(),
13183
13188
  brand: z.string().min(1).optional(),
13189
+ brandWhenSidebarCollapsed: z.enum(BRAND_WHEN_SIDEBAR_COLLAPSED).optional(),
13184
13190
  sidebarMenu: z.array(SidebarNavItemSchema).min(1).refine((items) => new Set(items.map((item) => item.id)).size === items.length, {
13185
13191
  message: "sidebarMenu: id must be unique"
13192
+ }).refine((items) => items.filter((item) => item.primary === true).length <= 1, {
13193
+ message: "sidebarMenu: at most one item can be primary"
13186
13194
  }).optional(),
13187
13195
  userMenu: z.array(SidebarMenuItemSchema).min(1).refine((items) => new Set(items.map((item) => item.id)).size === items.length, {
13188
13196
  message: "userMenu: id must be unique"
@@ -14876,7 +14884,10 @@ var ProviderRouter = class {
14876
14884
  if (next) return next;
14877
14885
  return {
14878
14886
  kind: "give-up",
14879
- message: recovery === "rotate_credential" ? t("provider_route.keys_exhausted") : message,
14887
+ message: recovery === "rotate_credential" ? t("provider_route.root_cause", {
14888
+ message: t("provider_route.credential_rejected"),
14889
+ cause: message
14890
+ }) : message,
14880
14891
  code
14881
14892
  };
14882
14893
  }
@@ -17589,21 +17600,32 @@ var SessionDB = class {
17589
17600
  search(input) {
17590
17601
  const limit = input.limit ?? 5;
17591
17602
  const scope = input.scope ?? "all";
17592
- if (scope === "title") {
17593
- const safe = "%" + sanitizeFtsQuery(input.query) + "%";
17594
- const rows = this.db.prepare(
17595
- `SELECT * FROM sessions WHERE archived = 0 AND title LIKE @q ORDER BY started_at DESC LIMIT @limit`
17596
- ).all({ q: safe, limit });
17597
- return {
17598
- results: rows.map((r) => ({
17599
- session: this.rowToMeta(r),
17600
- matches: [{ messageIndex: -1, snippet: r["title"] ?? "", score: 1 }],
17601
- score: 1
17602
- }))
17603
- };
17604
- }
17605
- const safeQuery = sanitizeFtsQuery(input.query);
17606
- if (!safeQuery) return { results: [] };
17603
+ if (scope === "title") return { results: this.searchTitles(input.query, limit) };
17604
+ const content = this.searchContent(input.query, limit);
17605
+ if (scope === "content") return { results: content };
17606
+ const titles = this.searchTitles(input.query, limit);
17607
+ const seen = new Set(titles.map((r) => r.session.id));
17608
+ return {
17609
+ results: [...titles, ...content.filter((r) => !seen.has(r.session.id))].slice(0, limit)
17610
+ };
17611
+ }
17612
+ searchTitles(query, limit) {
17613
+ const needle = query.trim();
17614
+ if (!needle) return [];
17615
+ const like = "%" + needle.replace(/[\\%_]/g, "\\$&") + "%";
17616
+ const rows = this.db.prepare(
17617
+ `SELECT * FROM sessions WHERE archived = 0 AND title LIKE @q ESCAPE '\\'
17618
+ ORDER BY started_at DESC LIMIT @limit`
17619
+ ).all({ q: like, limit });
17620
+ return rows.map((r) => ({
17621
+ session: this.rowToMeta(r),
17622
+ matches: [{ messageIndex: -1, snippet: r["title"] ?? "", score: 1 }],
17623
+ score: 1
17624
+ }));
17625
+ }
17626
+ searchContent(query, limit) {
17627
+ const safeQuery = sanitizeFtsQuery(query);
17628
+ if (!safeQuery) return [];
17607
17629
  const ftsQuery = buildFtsMatchQuery(safeQuery);
17608
17630
  const ftsRows = this.db.prepare(
17609
17631
  `
@@ -17650,7 +17672,7 @@ var SessionDB = class {
17650
17672
  score: 1
17651
17673
  });
17652
17674
  }
17653
- return { results: results2 };
17675
+ return results2;
17654
17676
  }
17655
17677
  const seen = /* @__PURE__ */ new Set();
17656
17678
  const results = [];
@@ -17671,7 +17693,7 @@ var SessionDB = class {
17671
17693
  score: 1
17672
17694
  });
17673
17695
  }
17674
- return { results };
17696
+ return results;
17675
17697
  }
17676
17698
  pruneCandidates(input) {
17677
17699
  const clauses = ["ended_at IS NOT NULL", "updated_at < @cutoff", "ended_at < @cutoff"];
@@ -19084,6 +19106,7 @@ function isLastOpenSession(value) {
19084
19106
  const v = value;
19085
19107
  return typeof v["root"] === "string" && v["root"].length > 0 && typeof v["sessionId"] === "string" && v["sessionId"].length > 0 && typeof v["at"] === "number";
19086
19108
  }
19109
+ var isWidthShaped = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
19087
19110
  var FILE_VERSION4 = 1;
19088
19111
  function describe9(err) {
19089
19112
  return err instanceof Error ? err.message : String(err);
@@ -19106,7 +19129,10 @@ var AppearanceStore = class {
19106
19129
  const value = patch[key];
19107
19130
  if (typeof value === "string" && value.length > 0) next[key] = value;
19108
19131
  }
19109
- if (next.theme === this.prefs.theme && next.lang === this.prefs.lang) return;
19132
+ if (isWidthShaped(patch.sidebarWidth)) next.sidebarWidth = patch.sidebarWidth;
19133
+ if (next.theme === this.prefs.theme && next.lang === this.prefs.lang && next.sidebarWidth === this.prefs.sidebarWidth) {
19134
+ return;
19135
+ }
19110
19136
  this.prefs = next;
19111
19137
  this.save();
19112
19138
  }
@@ -19130,6 +19156,7 @@ var AppearanceStore = class {
19130
19156
  if (file.version !== FILE_VERSION4) return;
19131
19157
  if (typeof file.theme === "string" && file.theme.length > 0) this.prefs.theme = file.theme;
19132
19158
  if (typeof file.lang === "string" && file.lang.length > 0) this.prefs.lang = file.lang;
19159
+ if (isWidthShaped(file.sidebarWidth)) this.prefs.sidebarWidth = file.sidebarWidth;
19133
19160
  }
19134
19161
  save() {
19135
19162
  const body2 = JSON.stringify(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epoch-agent/core",
3
- "version": "0.30.0",
3
+ "version": "1.1.0",
4
4
  "private": false,
5
5
  "description": "epoch-agent 核心引擎:ReAct 循环、Provider 路由、工具调度、记忆管理",
6
6
  "repository": {
@@ -27,8 +27,8 @@
27
27
  "gpt-tokenizer": "^3.4.0",
28
28
  "js-yaml": "^5.2.3",
29
29
  "zod": "^4.4.3",
30
- "@epoch-agent/infra": "0.30.0",
31
- "@epoch-agent/protocol": "0.30.0"
30
+ "@epoch-agent/infra": "1.1.0",
31
+ "@epoch-agent/protocol": "1.1.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@ai-sdk/alibaba": "^2.0.59",