@xopcai/xopc 0.0.206 → 0.0.207

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 (170) hide show
  1. package/README.md +7 -7
  2. package/README.zh-CN.md +7 -7
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store-URW-e_me.js → activity-store-BmpM0zwM.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BLK6kRCJ.js → agent-avatar-dicebear-DhK5wi6_.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-Bc3Lc-n2.js +68 -0
  8. package/dist/gateway/static/root/assets/{api-C_MS4arC.js → api-CzaAcDOn.js} +1 -1
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-CnUN6BJk.js → app-management-settings-panel-Dqj5G_cd.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-C8Nx8hZE.js → appearance-settings-Bm1uLGMi.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-BKtwU47-.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-C7FqeJZD.js → archive-plugin-CgnzBplN.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-DCYQgsYE.js → attachment-load-Cuybcmhn.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-ilGeRLDN.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-Bf1WROsh.js → binary-plugins-D6BBx6Ps.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-BPK08Pjv.js → block-editor-Dk1c3Spa.js} +3 -3
  17. package/dist/gateway/static/root/assets/browser-settings-page-BCu8AZbs.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-cqVoDHyp.js → browser-workflow-inputs-DvfIzCgV.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-Des1UTsS.js → browser-workflows-page-DZScuPlF.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-BbWQBtTe.js +7 -0
  21. package/dist/gateway/static/root/assets/{capability-presets-api-D4MjqV2a.js → capability-presets-api-hoA8R_J1.js} +1 -1
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BTVU46Yn.js +3 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-CcimZduy.js → channel-recipient-api-BS8I65NT.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-BEQsC9a9.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-DRwbgtOT.js +1 -0
  26. package/dist/gateway/static/root/assets/chat-terminal-dock-BIPhWBDI.js +36 -0
  27. package/dist/gateway/static/root/assets/{chat-terminal-dock-B1njb2Cr.css → chat-terminal-dock-uQUnjRtf.css} +1 -1
  28. package/dist/gateway/static/root/assets/{connectors-api-CUvFu8jh.js → connectors-api-B_78jmvM.js} +1 -1
  29. package/dist/gateway/static/root/assets/{connectors-page-BJoHjWnu.js → connectors-page-w_3kpqbc.js} +2 -2
  30. package/dist/gateway/static/root/assets/{cron-expression-hFSZZpvM.js → cron-expression-BBheaBIr.js} +1 -1
  31. package/dist/gateway/static/root/assets/{date-picker-CKZ0gc-Y.js → date-picker-CDwj7UrT.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-zv1oHtg4.js → dependency-picker-Dnrc2qZe.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-DY9ykMtD.js → desktop-pet-Bj_vUjXp.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-XiSmmt26.js → desktop-pet-settings-uiCwJJk4.js} +1 -1
  35. package/dist/gateway/static/root/assets/{directory-picker-path-field-CZkgk15r.js → directory-picker-path-field-D0zUQ-TO.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-debug-page-CTppsTEi.js → extension-debug-page-_GZ4y2da.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-CHRTUvAa.js → extension-page-scR96Edg.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-settings-page-z2UBx25A.js → extension-settings-page-CILsAwxx.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-api-DzFPJTnm.js → gateway-config-api-984O_4wM.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-config-swr-CGpoH1gU.js → gateway-config-swr-D4hvsdJA.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-settings-DBa2I6VM.js → gateway-settings-aF4eQHo3.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-Te-TREBt.js → gateway-startup-retry-Deo5-O87.js} +1 -1
  43. package/dist/gateway/static/root/assets/{heartbeat-settings-DyQGGdBu.js → heartbeat-settings-D5DrFWH6.js} +1 -1
  44. package/dist/gateway/static/root/assets/{home-page-EkT4eGeP.js → home-page-DiMWxngC.js} +2 -2
  45. package/dist/gateway/static/root/assets/{index-CrwXzRpA.js → index-DzKLVgY-.js} +47 -47
  46. package/dist/gateway/static/root/assets/index-wR5jX-lw.css +2 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-fb0zS8pk.js → keyboard-shortcuts-settings-DGmOlNcB.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-De8vuwu1.js +2 -0
  49. package/dist/gateway/static/root/assets/{local-apps-page-DFdheruU.js → local-apps-page-CzS2sCxg.js} +1 -1
  50. package/dist/gateway/static/root/assets/{locale-store-CieddUjx.js → locale-store-C7xtkP3D.js} +1 -1
  51. package/dist/gateway/static/root/assets/logs-page-BI9stsVO.js +2 -0
  52. package/dist/gateway/static/root/assets/{management-settings-D3PsQ612.js → management-settings-Cpxs43JB.js} +1 -1
  53. package/dist/gateway/static/root/assets/{markdown-split-x5K52Thz.js → markdown-split-CQvFHxUa.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-view-Cjjey5Y6.js → markdown-view-BRwrSbwM.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-DNtEkRAh.js → media-plugins-Bs9MsiaM.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-Dxk5Rzj_.js +3 -0
  57. package/dist/gateway/static/root/assets/{notes-page-nWEqlwDw.js → notes-page-Dux_g6aZ.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-CGafcgJ8.js +4 -0
  59. package/dist/gateway/static/root/assets/{preview-open-alternatives-CXcIKVi9.js → preview-open-alternatives-fvhtN4Y2.js} +1 -1
  60. package/dist/gateway/static/root/assets/{product-open-page-CZLJudPk.js → product-open-page-f_jbg-9N.js} +1 -1
  61. package/dist/gateway/static/root/assets/{project-detail-page-Cf1v94LO.js → project-detail-page-C6mNsjYr.js} +1 -1
  62. package/dist/gateway/static/root/assets/{projects-page-BRMZkNht.js → projects-page-D1G6VIxR.js} +1 -1
  63. package/dist/gateway/static/root/assets/remote-access-hub-CIez6X0x.js +1 -0
  64. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-RYjduQV6.js → runtime-tools-settings-panel-zapSiJrv.js} +1 -1
  65. package/dist/gateway/static/root/assets/{schema-form--1ZXg4qC.js → schema-form-CFyz8y5v.js} +1 -1
  66. package/dist/gateway/static/root/assets/sessions-page-6irxQjHb.js +1 -0
  67. package/dist/gateway/static/root/assets/settings-advanced-gate-CRb0QTG2.js +1 -0
  68. package/dist/gateway/static/root/assets/{settings-form-section-71-8j3zt.js → settings-form-section-DCiK4TIq.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-loading-skeleton-C5Jn1l0q.js → settings-loading-skeleton-DFUJEv4G.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-TYYGe6kZ.js → settings-page-Cnp9Bdd0.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-jA5I-17g.js → setup-status-panel-BFMGTGBO.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-BMUQIGfk.js → share-preview-page-DA8nA4cz.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-CaKfvJzQ.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-BOBUcYr5.js +1 -0
  75. package/dist/gateway/static/root/assets/{skills-page-BzZT1SKg.js → skills-page-BJJACxzz.js} +1 -1
  76. package/dist/gateway/static/root/assets/{skills-page.utils-DnaBw5Ji.js → skills-page.utils--1-vOg3V.js} +1 -1
  77. package/dist/gateway/static/root/assets/{system-settings-panel-DqiPQgVI.js → system-settings-panel-DY0lIaXY.js} +1 -1
  78. package/dist/gateway/static/root/assets/task-detail-page-Ciuwe7AG.js +1 -0
  79. package/dist/gateway/static/root/assets/{theme-store-BP3_RpaY.js → theme-store-DoyRfkoi.js} +1 -1
  80. package/dist/gateway/static/root/assets/{use-autosave-BJkQ-vpu.js → use-autosave-DzIR5Lxf.js} +1 -1
  81. package/dist/gateway/static/root/assets/{user-context-page-BP8-sOPi.js → user-context-page-yf18T_BZ.js} +1 -1
  82. package/dist/gateway/static/root/assets/{voice-api-key-field-C6c8e7Mx.js → voice-api-key-field-B7MZS8tS.js} +1 -1
  83. package/dist/gateway/static/root/assets/{work-discovery-overlay-CCNjWKql.js → work-discovery-overlay-zyX6yxxF.js} +1 -1
  84. package/dist/gateway/static/root/assets/work-discovery-page-2e5J0sIp.js +1 -0
  85. package/dist/gateway/static/root/assets/workflow-run-setup-panel-Cj1vPWRM.js +3 -0
  86. package/dist/gateway/static/root/assets/workflows-page-D37zWlWY.js +5 -0
  87. package/dist/gateway/static/root/assets/{working-directory-picker-modal-vWi33CZJ.js → working-directory-picker-modal-Bm7cox3y.js} +1 -1
  88. package/dist/gateway/static/root/index.html +10 -10
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/embedded/transcript-runtime.d.ts +2 -1
  91. package/dist/src/agent/embedded/transcript-runtime.js +38 -4
  92. package/dist/src/agent/inbound/inbound-loop.d.ts +1 -1
  93. package/dist/src/agent/memory/compaction-ledger.d.ts +11 -0
  94. package/dist/src/agent/memory/compaction-ledger.js +108 -0
  95. package/dist/src/agent/memory/compaction-serializer.d.ts +2 -0
  96. package/dist/src/agent/memory/compaction-serializer.js +52 -0
  97. package/dist/src/agent/memory/compaction-source-planner.d.ts +20 -0
  98. package/dist/src/agent/memory/compaction-source-planner.js +67 -0
  99. package/dist/src/agent/memory/compaction.d.ts +11 -5
  100. package/dist/src/agent/memory/compaction.js +245 -153
  101. package/dist/src/agent/prompt/sections/behavior.js +1 -1
  102. package/dist/src/agent/prompt/sections/memory-skills.js +4 -2
  103. package/dist/src/agent/prompt/sections/tooling.js +2 -0
  104. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  105. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  106. package/dist/src/agent/tools/factory.js +5 -0
  107. package/dist/src/agent/tools/index.d.ts +1 -0
  108. package/dist/src/agent/tools/index.js +2 -1
  109. package/dist/src/agent/tools/session-recall-tool.d.ts +7 -0
  110. package/dist/src/agent/tools/session-recall-tool.js +82 -0
  111. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  112. package/dist/src/config/agent-profile.js +1 -1
  113. package/dist/src/config/schema.d.ts +1 -0
  114. package/dist/src/gateway/agents-admin.js +1 -1
  115. package/dist/src/gateway/heartbeat/service.js +1 -1
  116. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
  117. package/dist/src/gateway/service/run-gateway-agent.js +3 -3
  118. package/dist/src/heartbeat/index.js +1 -1
  119. package/dist/src/session/compaction-types.d.ts +30 -0
  120. package/dist/src/session/compaction-types.js +35 -0
  121. package/dist/src/session/manager.d.ts +3 -0
  122. package/dist/src/session/session-context-for-llm.d.ts +4 -2
  123. package/dist/src/session/session-context-for-llm.js +2 -1
  124. package/dist/src/session/store.d.ts +10 -1
  125. package/dist/src/session/store.js +55 -23
  126. package/dist/src/session/types.d.ts +3 -2
  127. package/dist/src/storage/sqlite/index.d.ts +1 -1
  128. package/dist/src/storage/sqlite/index.js +2 -2
  129. package/dist/src/storage/sqlite/migrations/123_remove_v2_compaction_boundaries.sql +25 -0
  130. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  131. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  132. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  133. package/dist/src/storage/sqlite/schema.js +1 -1
  134. package/dist/src/storage/sqlite/transcript-repository.d.ts +24 -1
  135. package/dist/src/storage/sqlite/transcript-repository.js +78 -29
  136. package/dist/src/user-context/config.d.ts +4 -0
  137. package/dist/src/user-context/config.js +2 -0
  138. package/package.json +3 -3
  139. package/skills/THIRD_PARTY_NOTICES.md +1 -1
  140. package/skills/engineering/define-task/SKILL.md +48 -0
  141. package/skills/engineering/define-task/references/task-contract-rubric.md +15 -0
  142. package/dist/gateway/static/root/assets/agents-D5HVmdNx.js +0 -68
  143. package/dist/gateway/static/root/assets/apps-page-DKCA_LFY.js +0 -1
  144. package/dist/gateway/static/root/assets/automations-page-BEOE4ZKM.js +0 -6
  145. package/dist/gateway/static/root/assets/browser-settings-page-CLRmMdU9.js +0 -8
  146. package/dist/gateway/static/root/assets/capabilities-settings-panel-BNcVi4ar.js +0 -7
  147. package/dist/gateway/static/root/assets/capability-presets-settings-panel-uFwW2ah5.js +0 -3
  148. package/dist/gateway/static/root/assets/channels-settings-DSLP8OjS.js +0 -1
  149. package/dist/gateway/static/root/assets/channels-status-swr-D0OR6Ylw.js +0 -1
  150. package/dist/gateway/static/root/assets/chat-terminal-dock-wpi7abPg.js +0 -38
  151. package/dist/gateway/static/root/assets/index-BpLqHdfz.css +0 -2
  152. package/dist/gateway/static/root/assets/local-app-workbench-page-CCC3Cvb8.js +0 -2
  153. package/dist/gateway/static/root/assets/logs-page-B6jfkNDF.js +0 -2
  154. package/dist/gateway/static/root/assets/messages-CySMn8WL.js +0 -3
  155. package/dist/gateway/static/root/assets/notes-workbench-QstkgWsW.js +0 -4
  156. package/dist/gateway/static/root/assets/remote-access-hub-D55FTXZw.js +0 -1
  157. package/dist/gateway/static/root/assets/sessions-page-C5Yy6eIn.js +0 -1
  158. package/dist/gateway/static/root/assets/settings-advanced-gate-BqO_8bUh.js +0 -1
  159. package/dist/gateway/static/root/assets/shares-settings-Dru1a2rZ.js +0 -1
  160. package/dist/gateway/static/root/assets/skill-reload-api-C8iqS6kF.js +0 -1
  161. package/dist/gateway/static/root/assets/task-detail-page-DQP5vDr-.js +0 -1
  162. package/dist/gateway/static/root/assets/work-discovery-page-DL_Ie0s2.js +0 -1
  163. package/dist/gateway/static/root/assets/workflow-run-setup-panel-DLO-dMSN.js +0 -3
  164. package/dist/gateway/static/root/assets/workflows-page-B4-k2FHB.js +0 -5
  165. package/dist/src/agent/memory/compaction-planner.d.ts +0 -16
  166. package/dist/src/agent/memory/compaction-planner.js +0 -168
  167. package/dist/src/agent/memory/summary-generator.d.ts +0 -46
  168. package/dist/src/agent/memory/summary-generator.js +0 -229
  169. package/skills/engineering/define-goal/SKILL.md +0 -41
  170. package/skills/engineering/define-goal/references/objective-rubric.md +0 -12
@@ -0,0 +1,25 @@
1
+ DELETE FROM transcript_fts
2
+ WHERE entry_id IN (
3
+ SELECT entry_id
4
+ FROM transcript_entries
5
+ WHERE entry_kind = 'compaction'
6
+ );
7
+
8
+ DELETE FROM transcript_entries
9
+ WHERE entry_kind = 'compaction';
10
+
11
+ UPDATE sessions
12
+ SET
13
+ compacted_count = 0,
14
+ message_count = (
15
+ SELECT COUNT(*)
16
+ FROM transcript_entries e
17
+ WHERE e.session_id = sessions.session_id
18
+ AND e.entry_kind = 'message'
19
+ ),
20
+ estimated_tokens = (
21
+ SELECT COALESCE(SUM((length(COALESCE(json_extract(e.payload_json, '$.content'), '')) + 3) / 4), 0)
22
+ FROM transcript_entries e
23
+ WHERE e.session_id = sessions.session_id
24
+ AND e.entry_kind = 'message'
25
+ );
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 122;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 123;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
12
12
  /** Baseline schema version applied from schema.sql on first open. */
13
13
  const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
14
14
  /** Latest schema version this release supports (increment when adding migrations). */
15
- const XOPC_DB_SCHEMA_VERSION = 122;
15
+ const XOPC_DB_SCHEMA_VERSION = 123;
16
16
  const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
17
17
  function backupBeforeTaskCutover(db, databasePath) {
18
18
  db.exec("PRAGMA wal_checkpoint(FULL)");
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration) {
57
57
  * Each step runs in its own transaction and updates schema_meta on success.
58
58
  */
59
59
  function applyPendingMigrations(db, options = {}) {
60
- const targetVersion = options.targetVersion ?? 122;
60
+ const targetVersion = options.targetVersion ?? 123;
61
61
  let currentVersion = readSchemaVersion(db);
62
62
  if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
63
63
  if (currentVersion >= targetVersion) return currentVersion;
@@ -94,7 +94,7 @@ function applyPendingMigrations(db, options = {}) {
94
94
  }
95
95
  /** Inspect schema version without mutating the database. */
96
96
  function inspectSchemaMigrationStatus(db, options = {}) {
97
- const appVersion = options.targetVersion ?? 122;
97
+ const appVersion = options.targetVersion ?? 123;
98
98
  const dbVersion = readSchemaVersion(db);
99
99
  if (dbVersion > appVersion) return {
100
100
  dbVersion,
@@ -19,7 +19,7 @@ const log = createLogger('Sqlite:Migrations');
19
19
  export const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
20
20
 
21
21
  /** Latest schema version this release supports (increment when adding migrations). */
22
- export const XOPC_DB_SCHEMA_VERSION = 122;
22
+ export const XOPC_DB_SCHEMA_VERSION = 123;
23
23
 
24
24
  const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
25
25
 
@@ -32,7 +32,7 @@ function ensureXopcDatabaseSchema(db, options = {}) {
32
32
  currentVersion = 11;
33
33
  }
34
34
  applyPendingMigrations(db, {
35
- targetVersion: 122,
35
+ targetVersion: 123,
36
36
  databasePath: options.databasePath
37
37
  });
38
38
  }
@@ -2,11 +2,34 @@ import type { AgentMessage } from '@earendil-works/pi-agent-core';
2
2
  import type { CompactionBoundarySummary } from '../../session/types.js';
3
3
  import { type TranscriptStoredRow, type XopcTranscriptCompactionEntry } from '../../session/session-context-for-llm.js';
4
4
  import { type TranscriptEntryRow } from './row-mappers.js';
5
+ export interface TranscriptSourceEntry {
6
+ entryId: string;
7
+ seq: number;
8
+ createdAt: number;
9
+ row: TranscriptStoredRow;
10
+ }
11
+ export interface CompactionSourceSnapshot {
12
+ sessionId: string;
13
+ lastSeq: number;
14
+ entries: TranscriptSourceEntry[];
15
+ }
16
+ export interface SessionTranscriptRecallMatch {
17
+ entryId: string;
18
+ seq: number;
19
+ role: string | null;
20
+ createdAt: number;
21
+ content: string;
22
+ }
5
23
  export declare function appendTranscriptEntry(sessionKey: string, row: TranscriptStoredRow, opts?: {
6
24
  sessionId?: string;
7
25
  tokenDelta?: number;
8
26
  }): TranscriptEntryRow;
9
- export declare function appendCompactionBoundary(sessionKey: string, row: Omit<XopcTranscriptCompactionEntry, 'baseSeq'>): TranscriptEntryRow;
27
+ export declare function appendCompactionBoundaryIfUnchanged(sessionKey: string, expected: Pick<CompactionSourceSnapshot, 'sessionId' | 'lastSeq'>, row: Omit<XopcTranscriptCompactionEntry, 'baseSeq'>): TranscriptEntryRow | null;
28
+ export declare function loadCompactionSourceSnapshot(sessionKey: string): CompactionSourceSnapshot | null;
29
+ export declare function searchSessionTranscript(sessionKey: string, query: string, options?: {
30
+ limit?: number;
31
+ beforeSeq?: number;
32
+ }): SessionTranscriptRecallMatch[];
10
33
  export declare function loadTranscriptRowsForSession(sessionKey: string): TranscriptStoredRow[];
11
34
  export declare function loadTranscriptHistoryRowsForSession(sessionKey: string): TranscriptStoredRow[];
12
35
  export declare function loadTranscriptRows(sessionId: string): TranscriptStoredRow[];
@@ -1,6 +1,7 @@
1
1
  import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
2
2
  import { buildSessionContextForLlm, isRuntimeOnlyTranscriptMessage } from "../../session/session-context-for-llm.js";
3
3
  import { classifyStoredRow, estimateTokensFromMessages, extractFtsContent, transcriptEntryRowToStoredRow } from "./row-mappers.js";
4
+ import { escapeFts5Query } from "./fts.js";
4
5
  import { getCurrentSessionId, readCurrentSessionId } from "./session-repository.js";
5
6
  import { randomUUID } from "node:crypto";
6
7
  //#region src/storage/sqlite/transcript-repository.ts
@@ -58,13 +59,15 @@ function appendTranscriptEntry(sessionKey, row, opts) {
58
59
  return inserted;
59
60
  });
60
61
  }
61
- function appendCompactionBoundary(sessionKey, row) {
62
+ function appendCompactionBoundaryIfUnchanged(sessionKey, expected, row) {
62
63
  return runSqliteWriteTransaction((db) => {
63
64
  const sessionId = readCurrentSessionId(db, sessionKey);
64
65
  if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
66
+ if (sessionId !== expected.sessionId) return null;
67
+ if (nextSeq(db, sessionId) - 1 !== expected.lastSeq) return null;
65
68
  const boundary = {
66
69
  ...row,
67
- baseSeq: nextSeq(db, sessionId) - 1
70
+ baseSeq: expected.lastSeq
68
71
  };
69
72
  const inserted = insertEntry(db, {
70
73
  sessionId,
@@ -83,6 +86,65 @@ function appendCompactionBoundary(sessionKey, row) {
83
86
  return inserted;
84
87
  });
85
88
  }
89
+ function loadCompactionSourceSnapshot(sessionKey) {
90
+ const db = getSqliteDatabase();
91
+ const sessionId = getCurrentSessionId(sessionKey);
92
+ if (!sessionId) return null;
93
+ const rows = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
94
+ FROM transcript_entries
95
+ WHERE session_id = ?
96
+ ORDER BY seq ASC`).all(sessionId);
97
+ return {
98
+ sessionId,
99
+ lastSeq: rows.at(-1)?.seq ?? 0,
100
+ entries: rows.map((entry) => ({
101
+ entryId: entry.entry_id,
102
+ seq: entry.seq,
103
+ createdAt: entry.created_at,
104
+ row: transcriptEntryRowToStoredRow(entry)
105
+ }))
106
+ };
107
+ }
108
+ function searchSessionTranscript(sessionKey, query, options = {}) {
109
+ const sessionId = getCurrentSessionId(sessionKey);
110
+ const normalized = query.trim();
111
+ if (!sessionId || !normalized) return [];
112
+ const limit = Math.min(20, Math.max(1, options.limit ?? 8));
113
+ const beforeSeq = options.beforeSeq ?? Number.MAX_SAFE_INTEGER;
114
+ const db = getSqliteDatabase();
115
+ const ftsRows = db.prepare(`SELECT e.entry_id, e.seq, e.role, e.created_at, f.content
116
+ FROM transcript_fts f
117
+ JOIN transcript_entries e
118
+ ON e.session_id = f.session_id AND e.entry_id = f.entry_id
119
+ WHERE transcript_fts MATCH ?
120
+ AND f.session_id = ?
121
+ AND e.entry_kind <> 'compaction'
122
+ AND e.seq < ?
123
+ ORDER BY bm25(transcript_fts), e.seq DESC
124
+ LIMIT ?`).all(escapeFts5Query(normalized), sessionId, beforeSeq, limit);
125
+ const escapedLike = normalized.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
126
+ const literalRows = db.prepare(`SELECT entry_id, seq, role, created_at, payload_json AS content
127
+ FROM transcript_entries
128
+ WHERE session_id = ?
129
+ AND entry_kind <> 'compaction'
130
+ AND seq < ?
131
+ AND payload_json LIKE ? ESCAPE '\\'
132
+ ORDER BY seq DESC
133
+ LIMIT ?`).all(sessionId, beforeSeq, `%${escapedLike}%`, limit);
134
+ const seen = /* @__PURE__ */ new Set();
135
+ return [...ftsRows, ...literalRows].flatMap((row) => {
136
+ const result = row;
137
+ if (seen.has(result.entry_id)) return [];
138
+ seen.add(result.entry_id);
139
+ return [{
140
+ entryId: result.entry_id,
141
+ seq: result.seq,
142
+ role: result.role,
143
+ createdAt: result.created_at,
144
+ content: result.content
145
+ }];
146
+ }).slice(0, limit);
147
+ }
86
148
  function loadTranscriptRowsForSession(sessionKey) {
87
149
  const sessionId = getCurrentSessionId(sessionKey);
88
150
  if (!sessionId) return [];
@@ -210,7 +272,7 @@ function listCompactionBoundaries(sessionKey) {
210
272
  tokensBefore: payload.tokensBefore,
211
273
  tokensAfter: payload.tokensAfter,
212
274
  summaryPreview: payload.summary.slice(0, 500),
213
- restoredFromCompactionId: payload.restoredFromCompactionId
275
+ audit: payload.audit
214
276
  };
215
277
  });
216
278
  }
@@ -221,42 +283,29 @@ function restoreBeforeCompactionBoundary(sessionKey, compactionId) {
221
283
  const boundary = db.prepare(`SELECT seq FROM transcript_entries
222
284
  WHERE session_id = ? AND entry_id = ? AND entry_kind = 'compaction'`).get(sessionId, compactionId);
223
285
  if (!boundary) throw new Error(`Compaction boundary not found: ${compactionId}`);
224
- const restoredMessages = buildSessionContextForLlm(db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
286
+ const removedEntryIds = db.prepare(`SELECT entry_id
287
+ FROM transcript_entries
288
+ WHERE session_id = ? AND seq >= ?`).all(sessionId, boundary.seq);
289
+ for (const entry of removedEntryIds) db.prepare(`DELETE FROM transcript_fts WHERE entry_id = ?`).run(entry.entry_id);
290
+ db.prepare(`DELETE FROM transcript_entries WHERE session_id = ? AND seq >= ?`).run(sessionId, boundary.seq);
291
+ const remainingEntries = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
225
292
  FROM transcript_entries
226
- WHERE session_id = ? AND seq < ?
227
- ORDER BY seq ASC`).all(sessionId, boundary.seq).map(transcriptEntryRowToStoredRow));
293
+ WHERE session_id = ?
294
+ ORDER BY seq ASC`).all(sessionId);
295
+ const restoredMessages = buildSessionContextForLlm(remainingEntries.map(transcriptEntryRowToStoredRow));
228
296
  if (restoredMessages.length === 0) throw new Error(`No restorable context exists before compaction boundary: ${compactionId}`);
229
- const current = db.prepare(`SELECT estimated_tokens FROM sessions WHERE session_key = ?`).get(sessionKey);
230
297
  const tokensAfter = estimateTokensFromMessages(restoredMessages);
231
- const baseSeq = nextSeq(db, sessionId) - 1;
232
- insertEntry(db, {
233
- sessionId,
234
- sessionKey,
235
- row: {
236
- type: "compaction",
237
- at: (/* @__PURE__ */ new Date()).toISOString(),
238
- baseSeq,
239
- plannerVersion: 2,
240
- summaryModelRef: "logical-restore",
241
- qualityAudit: "disabled",
242
- summary: `Restored the effective context that existed before compaction boundary ${compactionId}.`,
243
- messages: restoredMessages,
244
- firstKeptIndex: 0,
245
- tokensBefore: current.estimated_tokens,
246
- tokensAfter,
247
- restoredFromCompactionId: compactionId
248
- }
249
- });
298
+ const compactedCount = remainingEntries.filter((entry) => entry.entry_kind === "compaction").length;
250
299
  const now = Date.now();
251
300
  db.prepare(`UPDATE sessions SET
252
301
  message_count = ?,
253
302
  estimated_tokens = ?,
254
- compacted_count = compacted_count + 1,
303
+ compacted_count = ?,
255
304
  updated_at = ?,
256
305
  last_accessed_at = ?,
257
306
  last_interaction_at = ?
258
- WHERE session_key = ?`).run(restoredMessages.length, tokensAfter, now, now, now, sessionKey);
307
+ WHERE session_key = ?`).run(restoredMessages.length, tokensAfter, compactedCount, now, now, now, sessionKey);
259
308
  });
260
309
  }
261
310
  //#endregion
262
- export { appendCompactionBoundary, appendTranscriptEntry, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary };
311
+ export { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript };
@@ -17,6 +17,7 @@ export declare const DEFAULT_CONTEXT_COMPACTION_POLICY: {
17
17
  summaryTimeoutMs: number;
18
18
  summaryRetries: number;
19
19
  qualityGuard: boolean;
20
+ gapAudit: boolean;
20
21
  minToolResultKeepChars: number;
21
22
  maxActiveTranscriptBytes: number;
22
23
  postCompactionSections: string[];
@@ -33,6 +34,7 @@ export declare const ContextCompactionPolicySchema: z.ZodDefault<z.ZodObject<{
33
34
  summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
34
35
  summaryRetries: z.ZodDefault<z.ZodNumber>;
35
36
  qualityGuard: z.ZodDefault<z.ZodBoolean>;
37
+ gapAudit: z.ZodDefault<z.ZodBoolean>;
36
38
  model: z.ZodOptional<z.ZodString>;
37
39
  minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
38
40
  maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
@@ -81,6 +83,7 @@ export declare const UserMemoryConfigSchema: z.ZodDefault<z.ZodObject<{
81
83
  summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
82
84
  summaryRetries: z.ZodDefault<z.ZodNumber>;
83
85
  qualityGuard: z.ZodDefault<z.ZodBoolean>;
86
+ gapAudit: z.ZodDefault<z.ZodBoolean>;
84
87
  model: z.ZodOptional<z.ZodString>;
85
88
  minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
86
89
  maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
@@ -188,6 +191,7 @@ export declare const UserContextConfigSchema: z.ZodDefault<z.ZodObject<{
188
191
  summaryTimeoutMs: z.ZodDefault<z.ZodNumber>;
189
192
  summaryRetries: z.ZodDefault<z.ZodNumber>;
190
193
  qualityGuard: z.ZodDefault<z.ZodBoolean>;
194
+ gapAudit: z.ZodDefault<z.ZodBoolean>;
191
195
  model: z.ZodOptional<z.ZodString>;
192
196
  minToolResultKeepChars: z.ZodDefault<z.ZodNumber>;
193
197
  maxActiveTranscriptBytes: z.ZodDefault<z.ZodNumber>;
@@ -31,6 +31,7 @@ var init_config = __esmMin((() => {
31
31
  summaryTimeoutMs: 18e4,
32
32
  summaryRetries: 2,
33
33
  qualityGuard: true,
34
+ gapAudit: true,
34
35
  minToolResultKeepChars: 1e3,
35
36
  maxActiveTranscriptBytes: 2e6,
36
37
  postCompactionSections: ["Session Startup", "Red Lines"]
@@ -47,6 +48,7 @@ var init_config = __esmMin((() => {
47
48
  summaryTimeoutMs: z.number().int().min(1e3).max(6e5).default(18e4),
48
49
  summaryRetries: z.number().int().min(0).max(5).default(2),
49
50
  qualityGuard: z.boolean().default(true),
51
+ gapAudit: z.boolean().default(true),
50
52
  model: z.string().min(1).optional(),
51
53
  minToolResultKeepChars: z.number().int().min(200).default(1e3),
52
54
  maxActiveTranscriptBytes: z.number().int().min(64e3).default(2e6),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.206",
3
+ "version": "0.0.207",
4
4
  "description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -38,7 +38,7 @@
38
38
  "desktop",
39
39
  "extensions",
40
40
  "gateway",
41
- "goal-loop-os",
41
+ "task-loop-os",
42
42
  "llm",
43
43
  "local-first",
44
44
  "mcp",
@@ -164,8 +164,8 @@
164
164
  "vitest": "4.1.5",
165
165
  "vue": "^3.5.35",
166
166
  "@xopcai/endpoint-tools-protocol": "0.0.0",
167
- "@xopcai/realtime-protocol": "0.0.0",
168
167
  "@xopcai/gateway-contract": "0.0.0",
168
+ "@xopcai/realtime-protocol": "0.0.0",
169
169
  "@xopcai/realtime-client": "0.0.0"
170
170
  },
171
171
  "scripts": {
@@ -4,7 +4,7 @@ The skills in this directory are maintained as part of xopc.
4
4
 
5
5
  ## 2026-07 built-in capability packs
6
6
 
7
- - `engineering/define-goal` and `creative/algorithmic-art` were designed after reviewing
7
+ - `engineering/define-task` and `creative/algorithmic-art` were designed after reviewing
8
8
  Apache-2.0-licensed reference material supplied during product planning. Their instructions and
9
9
  assets in this repository were written independently for xopc; no reference files or branding
10
10
  are redistributed here.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: define-task
3
+ description: Define, create, or refine an explicitly requested persistent xopc Task with a verifiable Task Contract; do not use for ordinary one-off work.
4
+ metadata:
5
+ xopc:
6
+ emoji: "🎯"
7
+ requires_tools:
8
+ - xopc_use
9
+ - tool_manual
10
+ ---
11
+
12
+ # Task definition
13
+
14
+ Use this skill only when the user explicitly asks to define, capture, create, or refine a persistent
15
+ xopc Task. Complete ordinary implementation and one-off requests directly without creating a Task.
16
+
17
+ ## Build the Task Contract
18
+
19
+ Express the requested result through the current Task Contract fields:
20
+
21
+ - `objective`: the observable result;
22
+ - `expectedOutputs`: concrete deliverables;
23
+ - `acceptanceCriteria`: checks that prove completion;
24
+ - `constraints`: material boundaries, prohibitions, or required conditions.
25
+
26
+ Preserve user-stated assumptions, risks, approval requirements, priority, Project association, and
27
+ dependencies when they are available. Do not invent authority or success criteria that materially
28
+ change the request.
29
+
30
+ ## Persist safely
31
+
32
+ 1. Use repository and conversation context to make the contract concrete.
33
+ 2. Ask one concise question only when a missing result, acceptance criterion, or boundary would
34
+ materially change the Task.
35
+ 3. Load the `xopc_use` manual before a non-trivial Task mutation.
36
+ 4. List and inspect current Tasks before creating one when duplication is plausible. Refine a
37
+ matching Task through its typed lifecycle instead of creating a competing Task.
38
+ 5. Use `createMode: "capture"` unless the user explicitly wants execution to start now. Use
39
+ `createMode: "start"` only for authorized immediate execution.
40
+ 6. Read the current Task version before revising an existing contract, and preserve fields the user
41
+ did not ask to change because contract revision replaces the complete contract.
42
+ 7. Verify the returned Task and report its delivery link when one is provided.
43
+
44
+ For bugs, include a reproducer and regression check. For performance work, name the metric,
45
+ threshold, method, and run count. For research, name the decision the research must enable and the
46
+ evidence standard.
47
+
48
+ Read `references/task-contract-rubric.md` when the Task needs a more careful contract review.
@@ -0,0 +1,15 @@
1
+ # Define-task contract rubric
2
+
3
+ Review the Task Contract against these questions:
4
+
5
+ 1. What observable result belongs in `objective`?
6
+ 2. Which concrete artifacts or state changes belong in `expectedOutputs`?
7
+ 3. Which binary or measurable checks belong in `acceptanceCriteria`?
8
+ 4. Which scope boundaries, prohibitions, or required conditions belong in `constraints`?
9
+ 5. Does execution require an approval, dependency, credential, or user decision that must be
10
+ represented before work starts?
11
+ 6. Is there already a matching Task that should be inspected or refined instead of duplicated?
12
+ 7. Should the Task be captured for later or explicitly started now?
13
+
14
+ Prefer inspectable evidence: a test passes, an artifact exists, a measured threshold is met, a report
15
+ supports a named decision, or a reviewer accepts stated criteria.