sphica 0.6.22 → 0.6.23
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/db/migrations/0009.sql +9 -0
- package/db/schema.sql +1 -1
- package/dist/capture.js +22 -3
- package/dist/cli.js +99 -25
- package/dist/deliver.js +22 -3
- package/dist/mcp-record.js +24 -5
- package/dist/mcp.js +23 -4
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "sphica",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.23",
|
|
5
5
|
"description": "Records Claude Code and Codex sessions on your machine and keeps past implementation and decisions, with their sources, for your agent to find.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "iroha924",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Both full-text indexes must hold terms() output as of revision 9, which includes the parts of camelCase and snake_case names, so they
|
|
2
|
+
-- are rebuilt as `sphica doctor --reindex` does. Tables, views, and triggers are the same as at revision 8.
|
|
3
|
+
|
|
4
|
+
insert into unit_fts (unit_fts) values ('delete-all');
|
|
5
|
+
insert into unit_fts (rowid, body, ident, alias) select id, body, ident, alias from unit_search_text;
|
|
6
|
+
insert into source_fts (source_fts) values ('delete-all');
|
|
7
|
+
insert into source_fts (rowid, lexemes) select id, sphica_terms(text) from source where indexed = 1;
|
|
8
|
+
|
|
9
|
+
pragma user_version = 9;
|
package/db/schema.sql
CHANGED
package/dist/capture.js
CHANGED
|
@@ -10827,6 +10827,12 @@ var segmenter = new Intl.Segmenter("ja", { granularity: "word" });
|
|
|
10827
10827
|
var HIRAGANA_ONLY = /^[\p{Script=Hiragana}ー]+$/u;
|
|
10828
10828
|
var STOP = new Set(["the", "a", "an", "of", "to", "in", "is", "and", "or", "for", "on", "it", "be"]);
|
|
10829
10829
|
var IDENT = /#\d+|[a-z0-9][a-z0-9_./#-]*[a-z0-9]/g;
|
|
10830
|
+
var WORD = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
10831
|
+
var JAPANESE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}ー々]+/u;
|
|
10832
|
+
var COMPOUND = /^[A-Za-z0-9_]*(?:[A-Za-z0-9]_|_[A-Za-z0-9]|[a-z0-9][A-Z])[A-Za-z0-9_]*$/;
|
|
10833
|
+
var CUT = /_+|(?<=[a-z0-9])(?=[A-Z])/;
|
|
10834
|
+
var MAX_PARTS = 6;
|
|
10835
|
+
var NAME_PART = /^(?:[A-Za-z]+[0-9]*|[0-9]+)$/;
|
|
10830
10836
|
var MAX_TERM = 100;
|
|
10831
10837
|
var OKURIGANA = /^(\p{Script=Han}+)[\p{Script=Hiragana}ー]+$/u;
|
|
10832
10838
|
function singular(w) {
|
|
@@ -10842,8 +10848,9 @@ function singular(w) {
|
|
|
10842
10848
|
return w.slice(0, -1);
|
|
10843
10849
|
return w.endsWith("s") && !/(?:ss|us|is)$/.test(w) ? w.slice(0, -1) : w;
|
|
10844
10850
|
}
|
|
10845
|
-
function terms(text) {
|
|
10846
|
-
const
|
|
10851
|
+
function terms(text, parts = true) {
|
|
10852
|
+
const nfkc = text.normalize("NFKC");
|
|
10853
|
+
const norm = nfkc.toLowerCase();
|
|
10847
10854
|
const out = [];
|
|
10848
10855
|
const keep = (w) => {
|
|
10849
10856
|
if (w.length > MAX_TERM || STOP.has(w) || HIRAGANA_ONLY.test(w))
|
|
@@ -10856,6 +10863,18 @@ function terms(text) {
|
|
|
10856
10863
|
for (const m of norm.matchAll(IDENT))
|
|
10857
10864
|
if (m[0].length >= 3)
|
|
10858
10865
|
keep(m[0]);
|
|
10866
|
+
if (parts)
|
|
10867
|
+
for (const [word] of nfkc.matchAll(WORD))
|
|
10868
|
+
for (const w of word.split(JAPANESE)) {
|
|
10869
|
+
if (w.length > MAX_TERM || !COMPOUND.test(w))
|
|
10870
|
+
continue;
|
|
10871
|
+
const cut = w.split(CUT).filter(Boolean);
|
|
10872
|
+
if (cut.length <= MAX_PARTS && cut.every((p) => NAME_PART.test(p))) {
|
|
10873
|
+
for (const p of cut)
|
|
10874
|
+
if (p.length >= 2)
|
|
10875
|
+
keep(p.toLowerCase());
|
|
10876
|
+
}
|
|
10877
|
+
}
|
|
10859
10878
|
return out.filter(Boolean);
|
|
10860
10879
|
}
|
|
10861
10880
|
var QUESTION = new Set([
|
|
@@ -11110,7 +11129,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
|
|
|
11110
11129
|
|
|
11111
11130
|
// server/src/sqlite.ts
|
|
11112
11131
|
var SCHEMA_GENERATION = 2;
|
|
11113
|
-
var SCHEMA_REVISION =
|
|
11132
|
+
var SCHEMA_REVISION = 9;
|
|
11114
11133
|
var sphicaHome = () => process.env.SPHICA_HOME || path2.join(os.homedir(), ".sphica");
|
|
11115
11134
|
var dbFile = () => process.env.SPHICA_DB || path2.join(sphicaHome(), "sphica.db");
|
|
11116
11135
|
function requireRuntime() {
|
package/dist/cli.js
CHANGED
|
@@ -3016,6 +3016,12 @@ var segmenter = new Intl.Segmenter("ja", { granularity: "word" });
|
|
|
3016
3016
|
var HIRAGANA_ONLY = /^[\p{Script=Hiragana}ー]+$/u;
|
|
3017
3017
|
var STOP = new Set(["the", "a", "an", "of", "to", "in", "is", "and", "or", "for", "on", "it", "be"]);
|
|
3018
3018
|
var IDENT = /#\d+|[a-z0-9][a-z0-9_./#-]*[a-z0-9]/g;
|
|
3019
|
+
var WORD = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
3020
|
+
var JAPANESE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}ー々]+/u;
|
|
3021
|
+
var COMPOUND = /^[A-Za-z0-9_]*(?:[A-Za-z0-9]_|_[A-Za-z0-9]|[a-z0-9][A-Z])[A-Za-z0-9_]*$/;
|
|
3022
|
+
var CUT = /_+|(?<=[a-z0-9])(?=[A-Z])/;
|
|
3023
|
+
var MAX_PARTS = 6;
|
|
3024
|
+
var NAME_PART = /^(?:[A-Za-z]+[0-9]*|[0-9]+)$/;
|
|
3019
3025
|
var MAX_TERM = 100;
|
|
3020
3026
|
var OKURIGANA = /^(\p{Script=Han}+)[\p{Script=Hiragana}ー]+$/u;
|
|
3021
3027
|
function singular(w) {
|
|
@@ -3031,8 +3037,9 @@ function singular(w) {
|
|
|
3031
3037
|
return w.slice(0, -1);
|
|
3032
3038
|
return w.endsWith("s") && !/(?:ss|us|is)$/.test(w) ? w.slice(0, -1) : w;
|
|
3033
3039
|
}
|
|
3034
|
-
function terms(text) {
|
|
3035
|
-
const
|
|
3040
|
+
function terms(text, parts = true) {
|
|
3041
|
+
const nfkc = text.normalize("NFKC");
|
|
3042
|
+
const norm = nfkc.toLowerCase();
|
|
3036
3043
|
const out = [];
|
|
3037
3044
|
const keep = (w) => {
|
|
3038
3045
|
if (w.length > MAX_TERM || STOP.has(w) || HIRAGANA_ONLY.test(w))
|
|
@@ -3045,6 +3052,18 @@ function terms(text) {
|
|
|
3045
3052
|
for (const m of norm.matchAll(IDENT))
|
|
3046
3053
|
if (m[0].length >= 3)
|
|
3047
3054
|
keep(m[0]);
|
|
3055
|
+
if (parts)
|
|
3056
|
+
for (const [word] of nfkc.matchAll(WORD))
|
|
3057
|
+
for (const w of word.split(JAPANESE)) {
|
|
3058
|
+
if (w.length > MAX_TERM || !COMPOUND.test(w))
|
|
3059
|
+
continue;
|
|
3060
|
+
const cut = w.split(CUT).filter(Boolean);
|
|
3061
|
+
if (cut.length <= MAX_PARTS && cut.every((p) => NAME_PART.test(p))) {
|
|
3062
|
+
for (const p of cut)
|
|
3063
|
+
if (p.length >= 2)
|
|
3064
|
+
keep(p.toLowerCase());
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3048
3067
|
return out.filter(Boolean);
|
|
3049
3068
|
}
|
|
3050
3069
|
var QUESTION = new Set([
|
|
@@ -3626,7 +3645,7 @@ ${indent}${caution(note)}` : ""}`);
|
|
|
3626
3645
|
|
|
3627
3646
|
// server/src/sqlite.ts
|
|
3628
3647
|
var SCHEMA_GENERATION = 2;
|
|
3629
|
-
var SCHEMA_REVISION =
|
|
3648
|
+
var SCHEMA_REVISION = 9;
|
|
3630
3649
|
var sphicaHome = () => process.env.SPHICA_HOME || path3.join(os2.homedir(), ".sphica");
|
|
3631
3650
|
var dbFile = () => process.env.SPHICA_DB || path3.join(sphicaHome(), "sphica.db");
|
|
3632
3651
|
function requireRuntime() {
|
|
@@ -16097,7 +16116,9 @@ var terms_golden_default = {
|
|
|
16097
16116
|
"server/src/db-write.ts",
|
|
16098
16117
|
"connectwriter",
|
|
16099
16118
|
"ot-123",
|
|
16100
|
-
"#201"
|
|
16119
|
+
"#201",
|
|
16120
|
+
"connect",
|
|
16121
|
+
"writer"
|
|
16101
16122
|
]
|
|
16102
16123
|
},
|
|
16103
16124
|
{
|
|
@@ -16110,21 +16131,39 @@ var terms_golden_default = {
|
|
|
16110
16131
|
"name",
|
|
16111
16132
|
"snake_case_name",
|
|
16112
16133
|
"camelcasename",
|
|
16113
|
-
"kebab-case-name"
|
|
16134
|
+
"kebab-case-name",
|
|
16135
|
+
"snake",
|
|
16136
|
+
"case",
|
|
16137
|
+
"name",
|
|
16138
|
+
"camel",
|
|
16139
|
+
"case",
|
|
16140
|
+
"name"
|
|
16114
16141
|
]
|
|
16115
16142
|
},
|
|
16116
16143
|
{
|
|
16117
16144
|
text: "fullwidth ABC 123 と カタカナ",
|
|
16118
16145
|
terms: ["fullwidth", "abc", "123", "カタカナ", "fullwidth", "abc", "123"]
|
|
16119
16146
|
},
|
|
16120
|
-
{
|
|
16121
|
-
|
|
16122
|
-
|
|
16147
|
+
{
|
|
16148
|
+
text: "書きました 書きます 書く",
|
|
16149
|
+
terms: ["書", "書", "書"]
|
|
16150
|
+
},
|
|
16151
|
+
{
|
|
16152
|
+
text: "emoji 🚀 と 絵文字 👍🏽 のあいだ",
|
|
16153
|
+
terms: ["emoji", "絵文字", "emoji"]
|
|
16154
|
+
},
|
|
16155
|
+
{
|
|
16156
|
+
text: "é café と が(が)",
|
|
16157
|
+
terms: ["é", "café", "caf"]
|
|
16158
|
+
},
|
|
16123
16159
|
{
|
|
16124
16160
|
text: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa base64 aGVsbG8gd29ybGQgaGVsbG8gd29ybGQ=",
|
|
16125
16161
|
terms: ["base64", "agvsbg8gd29ybgqgagvsbg8gd29ybgq", "base64", "agvsbg8gd29ybgqgagvsbg8gd29ybgq"]
|
|
16126
16162
|
},
|
|
16127
|
-
{
|
|
16163
|
+
{
|
|
16164
|
+
text: "the a an of to in is and or for on it be",
|
|
16165
|
+
terms: []
|
|
16166
|
+
},
|
|
16128
16167
|
{
|
|
16129
16168
|
text: "保存先は Postgres じゃなくて SQLite にしよう。各ユーザーに DB サーバーを立てさせたくない。",
|
|
16130
16169
|
terms: [
|
|
@@ -16159,10 +16198,13 @@ var terms_golden_default = {
|
|
|
16159
16198
|
"postgre"
|
|
16160
16199
|
]
|
|
16161
16200
|
},
|
|
16162
|
-
{
|
|
16201
|
+
{
|
|
16202
|
+
text: "WAL モードも有効にしておいて。",
|
|
16203
|
+
terms: ["wal", "モード", "有効", "wal"]
|
|
16204
|
+
},
|
|
16163
16205
|
{
|
|
16164
16206
|
text: "open() で journal_mode = wal を設定しました。",
|
|
16165
|
-
terms: ["open", "journal_mode", "wal", "設定", "open", "journal_mode", "wal"]
|
|
16207
|
+
terms: ["open", "journal_mode", "wal", "設定", "open", "journal_mode", "wal", "journal", "mode"]
|
|
16166
16208
|
},
|
|
16167
16209
|
{
|
|
16168
16210
|
text: "利用状況の送信(テレメトリ)は入れない。ローカルで完結させるのがこのアプリの売りだから。",
|
|
@@ -16186,15 +16228,24 @@ var terms_golden_default = {
|
|
|
16186
16228
|
},
|
|
16187
16229
|
{
|
|
16188
16230
|
text: "fetchCover に最大 3 回の再試行を入れました。",
|
|
16189
|
-
terms: ["fetchcover", "最大", "3", "回", "再", "試行", "入", "fetchcover"]
|
|
16231
|
+
terms: ["fetchcover", "最大", "3", "回", "再", "試行", "入", "fetchcover", "fetch", "cover"]
|
|
16232
|
+
},
|
|
16233
|
+
{
|
|
16234
|
+
text: "今日はここまで。お疲れさま。",
|
|
16235
|
+
terms: ["今日", "お疲れさま"]
|
|
16236
|
+
},
|
|
16237
|
+
{
|
|
16238
|
+
text: "お疲れさまでした。",
|
|
16239
|
+
terms: ["お疲れさま"]
|
|
16190
16240
|
},
|
|
16191
|
-
{ text: "今日はここまで。お疲れさま。", terms: ["今日", "お疲れさま"] },
|
|
16192
|
-
{ text: "お疲れさまでした。", terms: ["お疲れさま"] },
|
|
16193
16241
|
{
|
|
16194
16242
|
text: "入力の検証に zod を使うのもありかもね。まだ決めないけど。",
|
|
16195
16243
|
terms: ["入力", "検証", "zod", "使", "決", "zod"]
|
|
16196
16244
|
},
|
|
16197
|
-
{
|
|
16245
|
+
{
|
|
16246
|
+
text: "候補として覚えておきます。",
|
|
16247
|
+
terms: ["候補", "覚"]
|
|
16248
|
+
},
|
|
16198
16249
|
{
|
|
16199
16250
|
text: "Store every timestamp in UTC. Convert to local time only when showing it.",
|
|
16200
16251
|
terms: [
|
|
@@ -16238,7 +16289,8 @@ var terms_golden_default = {
|
|
|
16238
16289
|
"write",
|
|
16239
16290
|
"iso",
|
|
16240
16291
|
"8601",
|
|
16241
|
-
"utc"
|
|
16292
|
+
"utc",
|
|
16293
|
+
"stored"
|
|
16242
16294
|
]
|
|
16243
16295
|
},
|
|
16244
16296
|
{
|
|
@@ -16282,7 +16334,9 @@ var terms_golden_default = {
|
|
|
16282
16334
|
"there",
|
|
16283
16335
|
"reverted",
|
|
16284
16336
|
"main",
|
|
16285
|
-
"thread"
|
|
16337
|
+
"thread",
|
|
16338
|
+
"offscreen",
|
|
16339
|
+
"canva"
|
|
16286
16340
|
]
|
|
16287
16341
|
},
|
|
16288
16342
|
{
|
|
@@ -16301,9 +16355,18 @@ var terms_golden_default = {
|
|
|
16301
16355
|
text: "検索結果のキャッシュを Redis に置きます。",
|
|
16302
16356
|
terms: ["検索", "結果", "キャッシュ", "redis", "置", "redis"]
|
|
16303
16357
|
},
|
|
16304
|
-
{
|
|
16305
|
-
|
|
16306
|
-
|
|
16358
|
+
{
|
|
16359
|
+
text: "ログその1を受け取りました。",
|
|
16360
|
+
terms: ["ログ", "1", "受け取り"]
|
|
16361
|
+
},
|
|
16362
|
+
{
|
|
16363
|
+
text: "ログその2を受け取りました。",
|
|
16364
|
+
terms: ["ログ", "2", "受け取り"]
|
|
16365
|
+
},
|
|
16366
|
+
{
|
|
16367
|
+
text: "ログその3を受け取りました。",
|
|
16368
|
+
terms: ["ログ", "3", "受け取り"]
|
|
16369
|
+
},
|
|
16307
16370
|
{
|
|
16308
16371
|
text: "CSV export leaks private notes",
|
|
16309
16372
|
terms: ["csv", "export", "leak", "private", "note", "csv", "export", "leak", "private", "note"]
|
|
@@ -16343,7 +16406,10 @@ var terms_golden_default = {
|
|
|
16343
16406
|
"csv"
|
|
16344
16407
|
]
|
|
16345
16408
|
},
|
|
16346
|
-
{
|
|
16409
|
+
{
|
|
16410
|
+
text: "Use pnpm for installs",
|
|
16411
|
+
terms: ["use", "pnpm", "install", "use", "pnpm", "install"]
|
|
16412
|
+
},
|
|
16347
16413
|
{
|
|
16348
16414
|
text: "Switch the lockfile to pnpm. npm install took minutes on CI.",
|
|
16349
16415
|
terms: [
|
|
@@ -16421,7 +16487,10 @@ var terms_golden_default = {
|
|
|
16421
16487
|
text: "Consider synchronous = OFF for speed.",
|
|
16422
16488
|
terms: ["consider", "synchronous", "off", "speed", "consider", "synchronous", "off", "speed"]
|
|
16423
16489
|
},
|
|
16424
|
-
{
|
|
16490
|
+
{
|
|
16491
|
+
text: "chore: switch to pnpm",
|
|
16492
|
+
terms: ["chore", "switch", "pnpm", "chore", "switch", "pnpm"]
|
|
16493
|
+
},
|
|
16425
16494
|
{
|
|
16426
16495
|
text: "Exclude notes from CSV export",
|
|
16427
16496
|
terms: ["exclude", "note", "from", "csv", "export", "exclude", "note", "from", "csv", "export"]
|
|
@@ -16444,7 +16513,8 @@ var terms_golden_default = {
|
|
|
16444
16513
|
"write",
|
|
16445
16514
|
"title",
|
|
16446
16515
|
"author",
|
|
16447
|
-
"only"
|
|
16516
|
+
"only",
|
|
16517
|
+
"csv"
|
|
16448
16518
|
]
|
|
16449
16519
|
},
|
|
16450
16520
|
{
|
|
@@ -16484,10 +16554,14 @@ var terms_golden_default = {
|
|
|
16484
16554
|
"drop",
|
|
16485
16555
|
"author",
|
|
16486
16556
|
"from",
|
|
16487
|
-
"export"
|
|
16557
|
+
"export",
|
|
16558
|
+
"csv"
|
|
16488
16559
|
]
|
|
16489
16560
|
},
|
|
16490
|
-
{
|
|
16561
|
+
{
|
|
16562
|
+
text: "検索は前方一致にする",
|
|
16563
|
+
terms: ["検索", "前方", "一致"]
|
|
16564
|
+
},
|
|
16491
16565
|
{
|
|
16492
16566
|
text: "書名の検索は前方一致にする。全文検索はデータが 1 万冊を超えるまで見送る。",
|
|
16493
16567
|
terms: ["書名", "検索", "前方", "一致", "全文", "検索", "データ", "1", "万", "冊", "超", "見送"]
|
package/dist/deliver.js
CHANGED
|
@@ -28,6 +28,12 @@ var segmenter = new Intl.Segmenter("ja", { granularity: "word" });
|
|
|
28
28
|
var HIRAGANA_ONLY = /^[\p{Script=Hiragana}ー]+$/u;
|
|
29
29
|
var STOP = new Set(["the", "a", "an", "of", "to", "in", "is", "and", "or", "for", "on", "it", "be"]);
|
|
30
30
|
var IDENT = /#\d+|[a-z0-9][a-z0-9_./#-]*[a-z0-9]/g;
|
|
31
|
+
var WORD = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
32
|
+
var JAPANESE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}ー々]+/u;
|
|
33
|
+
var COMPOUND = /^[A-Za-z0-9_]*(?:[A-Za-z0-9]_|_[A-Za-z0-9]|[a-z0-9][A-Z])[A-Za-z0-9_]*$/;
|
|
34
|
+
var CUT = /_+|(?<=[a-z0-9])(?=[A-Z])/;
|
|
35
|
+
var MAX_PARTS = 6;
|
|
36
|
+
var NAME_PART = /^(?:[A-Za-z]+[0-9]*|[0-9]+)$/;
|
|
31
37
|
var MAX_TERM = 100;
|
|
32
38
|
var OKURIGANA = /^(\p{Script=Han}+)[\p{Script=Hiragana}ー]+$/u;
|
|
33
39
|
function singular(w) {
|
|
@@ -43,8 +49,9 @@ function singular(w) {
|
|
|
43
49
|
return w.slice(0, -1);
|
|
44
50
|
return w.endsWith("s") && !/(?:ss|us|is)$/.test(w) ? w.slice(0, -1) : w;
|
|
45
51
|
}
|
|
46
|
-
function terms(text) {
|
|
47
|
-
const
|
|
52
|
+
function terms(text, parts = true) {
|
|
53
|
+
const nfkc = text.normalize("NFKC");
|
|
54
|
+
const norm = nfkc.toLowerCase();
|
|
48
55
|
const out = [];
|
|
49
56
|
const keep = (w) => {
|
|
50
57
|
if (w.length > MAX_TERM || STOP.has(w) || HIRAGANA_ONLY.test(w))
|
|
@@ -57,6 +64,18 @@ function terms(text) {
|
|
|
57
64
|
for (const m of norm.matchAll(IDENT))
|
|
58
65
|
if (m[0].length >= 3)
|
|
59
66
|
keep(m[0]);
|
|
67
|
+
if (parts)
|
|
68
|
+
for (const [word] of nfkc.matchAll(WORD))
|
|
69
|
+
for (const w of word.split(JAPANESE)) {
|
|
70
|
+
if (w.length > MAX_TERM || !COMPOUND.test(w))
|
|
71
|
+
continue;
|
|
72
|
+
const cut = w.split(CUT).filter(Boolean);
|
|
73
|
+
if (cut.length <= MAX_PARTS && cut.every((p) => NAME_PART.test(p))) {
|
|
74
|
+
for (const p of cut)
|
|
75
|
+
if (p.length >= 2)
|
|
76
|
+
keep(p.toLowerCase());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
60
79
|
return out.filter(Boolean);
|
|
61
80
|
}
|
|
62
81
|
var QUESTION = new Set([
|
|
@@ -11135,7 +11154,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
|
|
|
11135
11154
|
|
|
11136
11155
|
// server/src/sqlite.ts
|
|
11137
11156
|
var SCHEMA_GENERATION = 2;
|
|
11138
|
-
var SCHEMA_REVISION =
|
|
11157
|
+
var SCHEMA_REVISION = 9;
|
|
11139
11158
|
var sphicaHome = () => process.env.SPHICA_HOME || path3.join(os.homedir(), ".sphica");
|
|
11140
11159
|
var dbFile = () => process.env.SPHICA_DB || path3.join(sphicaHome(), "sphica.db");
|
|
11141
11160
|
function requireRuntime() {
|
package/dist/mcp-record.js
CHANGED
|
@@ -45542,6 +45542,12 @@ var segmenter = new Intl.Segmenter("ja", { granularity: "word" });
|
|
|
45542
45542
|
var HIRAGANA_ONLY = /^[\p{Script=Hiragana}ー]+$/u;
|
|
45543
45543
|
var STOP = new Set(["the", "a", "an", "of", "to", "in", "is", "and", "or", "for", "on", "it", "be"]);
|
|
45544
45544
|
var IDENT = /#\d+|[a-z0-9][a-z0-9_./#-]*[a-z0-9]/g;
|
|
45545
|
+
var WORD = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
45546
|
+
var JAPANESE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}ー々]+/u;
|
|
45547
|
+
var COMPOUND = /^[A-Za-z0-9_]*(?:[A-Za-z0-9]_|_[A-Za-z0-9]|[a-z0-9][A-Z])[A-Za-z0-9_]*$/;
|
|
45548
|
+
var CUT = /_+|(?<=[a-z0-9])(?=[A-Z])/;
|
|
45549
|
+
var MAX_PARTS = 6;
|
|
45550
|
+
var NAME_PART = /^(?:[A-Za-z]+[0-9]*|[0-9]+)$/;
|
|
45545
45551
|
var MAX_TERM = 100;
|
|
45546
45552
|
var OKURIGANA = /^(\p{Script=Han}+)[\p{Script=Hiragana}ー]+$/u;
|
|
45547
45553
|
function singular(w) {
|
|
@@ -45557,8 +45563,9 @@ function singular(w) {
|
|
|
45557
45563
|
return w.slice(0, -1);
|
|
45558
45564
|
return w.endsWith("s") && !/(?:ss|us|is)$/.test(w) ? w.slice(0, -1) : w;
|
|
45559
45565
|
}
|
|
45560
|
-
function terms(text) {
|
|
45561
|
-
const
|
|
45566
|
+
function terms(text, parts = true) {
|
|
45567
|
+
const nfkc = text.normalize("NFKC");
|
|
45568
|
+
const norm = nfkc.toLowerCase();
|
|
45562
45569
|
const out = [];
|
|
45563
45570
|
const keep = (w) => {
|
|
45564
45571
|
if (w.length > MAX_TERM || STOP.has(w) || HIRAGANA_ONLY.test(w))
|
|
@@ -45571,6 +45578,18 @@ function terms(text) {
|
|
|
45571
45578
|
for (const m of norm.matchAll(IDENT))
|
|
45572
45579
|
if (m[0].length >= 3)
|
|
45573
45580
|
keep(m[0]);
|
|
45581
|
+
if (parts)
|
|
45582
|
+
for (const [word] of nfkc.matchAll(WORD))
|
|
45583
|
+
for (const w of word.split(JAPANESE)) {
|
|
45584
|
+
if (w.length > MAX_TERM || !COMPOUND.test(w))
|
|
45585
|
+
continue;
|
|
45586
|
+
const cut = w.split(CUT).filter(Boolean);
|
|
45587
|
+
if (cut.length <= MAX_PARTS && cut.every((p) => NAME_PART.test(p))) {
|
|
45588
|
+
for (const p of cut)
|
|
45589
|
+
if (p.length >= 2)
|
|
45590
|
+
keep(p.toLowerCase());
|
|
45591
|
+
}
|
|
45592
|
+
}
|
|
45574
45593
|
return out.filter(Boolean);
|
|
45575
45594
|
}
|
|
45576
45595
|
var QUESTION = new Set([
|
|
@@ -45871,7 +45890,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
|
|
|
45871
45890
|
|
|
45872
45891
|
// server/src/sqlite.ts
|
|
45873
45892
|
var SCHEMA_GENERATION = 2;
|
|
45874
|
-
var SCHEMA_REVISION =
|
|
45893
|
+
var SCHEMA_REVISION = 9;
|
|
45875
45894
|
var sphicaHome = () => process.env.SPHICA_HOME || path2.join(os.homedir(), ".sphica");
|
|
45876
45895
|
var dbFile = () => process.env.SPHICA_DB || path2.join(sphicaHome(), "sphica.db");
|
|
45877
45896
|
function requireRuntime() {
|
|
@@ -47885,13 +47904,13 @@ var isoDate = (v) => {
|
|
|
47885
47904
|
const d = new Date(`${v}T00:00:00Z`);
|
|
47886
47905
|
return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 10) === v;
|
|
47887
47906
|
};
|
|
47888
|
-
var
|
|
47907
|
+
var WORD2 = /[\p{Script=Latin}\p{Script=Greek}\p{Script=Cyrillic}\p{M}\p{N}_]/u;
|
|
47889
47908
|
var NUMBER = /(?<![\p{Script=Latin}\p{Script=Greek}\p{Script=Cyrillic}\p{M}\p{N}\p{Pd}_.+\uFF0B\u2212])[+-]?(?:[0-9]{1,3}(?:,[0-9]{3})+(?![0-9])|[0-9]+)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/gu;
|
|
47890
47909
|
function standsAlone(quote, value) {
|
|
47891
47910
|
for (let at = quote.indexOf(value);at >= 0; at = quote.indexOf(value, at + 1)) {
|
|
47892
47911
|
const before = [...quote.slice(Math.max(0, at - 2), at)].at(-1) ?? "";
|
|
47893
47912
|
const after = String.fromCodePoint(quote.codePointAt(at + value.length) ?? 32);
|
|
47894
|
-
if (!
|
|
47913
|
+
if (!WORD2.test(before) && !WORD2.test(after))
|
|
47895
47914
|
return true;
|
|
47896
47915
|
}
|
|
47897
47916
|
return false;
|
package/dist/mcp.js
CHANGED
|
@@ -34729,6 +34729,12 @@ var segmenter = new Intl.Segmenter("ja", { granularity: "word" });
|
|
|
34729
34729
|
var HIRAGANA_ONLY = /^[\p{Script=Hiragana}ー]+$/u;
|
|
34730
34730
|
var STOP = new Set(["the", "a", "an", "of", "to", "in", "is", "and", "or", "for", "on", "it", "be"]);
|
|
34731
34731
|
var IDENT = /#\d+|[a-z0-9][a-z0-9_./#-]*[a-z0-9]/g;
|
|
34732
|
+
var WORD = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
34733
|
+
var JAPANESE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}ー々]+/u;
|
|
34734
|
+
var COMPOUND = /^[A-Za-z0-9_]*(?:[A-Za-z0-9]_|_[A-Za-z0-9]|[a-z0-9][A-Z])[A-Za-z0-9_]*$/;
|
|
34735
|
+
var CUT = /_+|(?<=[a-z0-9])(?=[A-Z])/;
|
|
34736
|
+
var MAX_PARTS = 6;
|
|
34737
|
+
var NAME_PART = /^(?:[A-Za-z]+[0-9]*|[0-9]+)$/;
|
|
34732
34738
|
var MAX_TERM = 100;
|
|
34733
34739
|
var OKURIGANA = /^(\p{Script=Han}+)[\p{Script=Hiragana}ー]+$/u;
|
|
34734
34740
|
function singular(w) {
|
|
@@ -34745,8 +34751,9 @@ function singular(w) {
|
|
|
34745
34751
|
return w.endsWith("s") && !/(?:ss|us|is)$/.test(w) ? w.slice(0, -1) : w;
|
|
34746
34752
|
}
|
|
34747
34753
|
var identTerm = (x) => singular(x.normalize("NFKC").toLowerCase());
|
|
34748
|
-
function terms(text) {
|
|
34749
|
-
const
|
|
34754
|
+
function terms(text, parts = true) {
|
|
34755
|
+
const nfkc = text.normalize("NFKC");
|
|
34756
|
+
const norm = nfkc.toLowerCase();
|
|
34750
34757
|
const out = [];
|
|
34751
34758
|
const keep = (w) => {
|
|
34752
34759
|
if (w.length > MAX_TERM || STOP.has(w) || HIRAGANA_ONLY.test(w))
|
|
@@ -34759,6 +34766,18 @@ function terms(text) {
|
|
|
34759
34766
|
for (const m of norm.matchAll(IDENT))
|
|
34760
34767
|
if (m[0].length >= 3)
|
|
34761
34768
|
keep(m[0]);
|
|
34769
|
+
if (parts)
|
|
34770
|
+
for (const [word] of nfkc.matchAll(WORD))
|
|
34771
|
+
for (const w of word.split(JAPANESE)) {
|
|
34772
|
+
if (w.length > MAX_TERM || !COMPOUND.test(w))
|
|
34773
|
+
continue;
|
|
34774
|
+
const cut = w.split(CUT).filter(Boolean);
|
|
34775
|
+
if (cut.length <= MAX_PARTS && cut.every((p) => NAME_PART.test(p))) {
|
|
34776
|
+
for (const p of cut)
|
|
34777
|
+
if (p.length >= 2)
|
|
34778
|
+
keep(p.toLowerCase());
|
|
34779
|
+
}
|
|
34780
|
+
}
|
|
34762
34781
|
return out.filter(Boolean);
|
|
34763
34782
|
}
|
|
34764
34783
|
var QUESTION = new Set([
|
|
@@ -34805,7 +34824,7 @@ var QUESTION = new Set([
|
|
|
34805
34824
|
]);
|
|
34806
34825
|
var FOLDED_QUESTION = new Set([...QUESTION].flatMap((w) => terms(w)));
|
|
34807
34826
|
function queryTerms(question) {
|
|
34808
|
-
return [...new Set(terms(question).filter((w) => !FOLDED_QUESTION.has(w)))].slice(0, 24);
|
|
34827
|
+
return [...new Set(terms(question, false).filter((w) => !FOLDED_QUESTION.has(w)))].slice(0, 24);
|
|
34809
34828
|
}
|
|
34810
34829
|
function ftsQuery(question) {
|
|
34811
34830
|
const ws = queryTerms(question);
|
|
@@ -45692,7 +45711,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
|
|
|
45692
45711
|
|
|
45693
45712
|
// server/src/sqlite.ts
|
|
45694
45713
|
var SCHEMA_GENERATION = 2;
|
|
45695
|
-
var SCHEMA_REVISION =
|
|
45714
|
+
var SCHEMA_REVISION = 9;
|
|
45696
45715
|
var sphicaHome = () => process.env.SPHICA_HOME || path2.join(os.homedir(), ".sphica");
|
|
45697
45716
|
var dbFile = () => process.env.SPHICA_DB || path2.join(sphicaHome(), "sphica.db");
|
|
45698
45717
|
function requireRuntime() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sphica",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.23",
|
|
4
4
|
"description": "Records Claude Code and Codex sessions on your machine and keeps past implementation and decisions, with their sources, for your agent to find.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|