pi-anchor 0.3.0 → 0.4.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/README.md +33 -170
- package/README_zh.md +32 -176
- package/assets/hero-en.svg +23 -39
- package/assets/hero-zh.svg +23 -39
- package/bin/anchor.js +36 -69
- package/dist/chunk-LKY6WIKH.js +1100 -0
- package/dist/extension-B1-fzCox.d.cts +167 -0
- package/dist/extension-B1-fzCox.d.ts +167 -0
- package/dist/extension.cjs +369 -1315
- package/dist/extension.d.cts +2 -20
- package/dist/extension.d.ts +2 -20
- package/dist/extension.js +4 -536
- package/dist/index.cjs +317 -1143
- package/dist/index.d.cts +17 -250
- package/dist/index.d.ts +17 -250
- package/dist/index.js +15 -103
- package/package.json +2 -2
- package/src/extension.ts +124 -362
- package/src/index.ts +1 -6
- package/src/store.ts +294 -424
- package/src/tui.ts +102 -297
- package/src/types.ts +24 -65
- package/dist/chunk-Q7IILJFA.js +0 -1563
- package/dist/store-t2_TDhJn.d.cts +0 -210
- package/dist/store-t2_TDhJn.d.ts +0 -210
- package/src/context_injector.ts +0 -166
- package/src/decay.ts +0 -125
- package/src/matcher.ts +0 -202
- package/src/observer.ts +0 -141
- package/src/protocol.ts +0 -95
- package/src/settlement.ts +0 -140
package/assets/hero-zh.svg
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 390" width="840" height="390">
|
|
2
2
|
<defs>
|
|
3
3
|
<filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
|
|
4
4
|
<feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
|
|
@@ -10,72 +10,56 @@
|
|
|
10
10
|
</defs>
|
|
11
11
|
|
|
12
12
|
<g filter="url(#shadow)">
|
|
13
|
-
<rect x="20" y="15" width="800" height="
|
|
13
|
+
<rect x="20" y="15" width="800" height="350" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
|
|
14
14
|
<path d="M 20,27 A 12,12 0 0,1 32,15 L 808,15 A 12,12 0 0,1 820,27 L 820,52 L 20,52 Z" fill="url(#headerGrad)" stroke="#343f44" stroke-width="1" />
|
|
15
15
|
<line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
|
|
16
16
|
<circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
|
|
17
17
|
<circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
|
|
18
18
|
<circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
|
|
19
19
|
<text x="420" y="38" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="500" fill="#859289">
|
|
20
|
-
⌖ anchor
|
|
20
|
+
⌖ anchor · 贴在终端边框上的电子便签
|
|
21
21
|
</text>
|
|
22
22
|
</g>
|
|
23
23
|
|
|
24
24
|
<g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
|
|
25
|
-
<text x="45" y="
|
|
26
|
-
<tspan fill="#a7c080" font-weight="bold">~/Workspace</tspan>
|
|
25
|
+
<text x="45" y="86">
|
|
26
|
+
<tspan fill="#a7c080" font-weight="bold">~/Workspace/app</tspan>
|
|
27
27
|
<tspan fill="#7fbbb3"> ❯ </tspan>
|
|
28
28
|
<tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
|
|
29
29
|
</text>
|
|
30
30
|
|
|
31
|
-
<text x="45" y="
|
|
32
|
-
<tspan fill="#7fbbb3" font-weight="bold">⌖
|
|
33
|
-
<tspan fill="#859289">(3 active, 1 quiet · 0 仓库污染 · 0 闲置 Token):</tspan>
|
|
31
|
+
<text x="45" y="120">
|
|
32
|
+
<tspan fill="#7fbbb3" font-weight="bold">⌖ Notes (3):</tspan>
|
|
34
33
|
</text>
|
|
35
34
|
|
|
36
|
-
<text x="45" y="
|
|
35
|
+
<text x="45" y="154">
|
|
37
36
|
<tspan fill="#859289"> 01 </tspan>
|
|
38
|
-
<tspan fill="#
|
|
39
|
-
<tspan fill="#
|
|
40
|
-
<tspan fill="#
|
|
41
|
-
<tspan fill="#e67e80" font-weight="bold">Today </tspan>
|
|
42
|
-
<tspan fill="#7a8478">Today 10:02</tspan>
|
|
37
|
+
<tspan fill="#d3c6aa">把登录 Token 改用 HttpOnly Cookie 存储 </tspan>
|
|
38
|
+
<tspan fill="#7fbbb3">app · auth.ts </tspan>
|
|
39
|
+
<tspan fill="#7a8478">25m ago</tspan>
|
|
43
40
|
</text>
|
|
44
41
|
|
|
45
42
|
<text x="45" y="182">
|
|
46
43
|
<tspan fill="#859289"> 02 </tspan>
|
|
47
|
-
<tspan fill="#
|
|
48
|
-
<tspan fill="#
|
|
49
|
-
<tspan fill="#
|
|
50
|
-
<tspan fill="#dbbc7f">Tomorrow </tspan>
|
|
51
|
-
<tspan fill="#7a8478">Yesterday 21:34</tspan>
|
|
44
|
+
<tspan fill="#d3c6aa">检查网关超时后的降级重试边界 </tspan>
|
|
45
|
+
<tspan fill="#7fbbb3">app · gateway.ts </tspan>
|
|
46
|
+
<tspan fill="#7a8478">3h ago</tspan>
|
|
52
47
|
</text>
|
|
53
48
|
|
|
54
|
-
<text x="45" y="
|
|
49
|
+
<text x="45" y="210">
|
|
55
50
|
<tspan fill="#859289"> 03 </tspan>
|
|
56
|
-
<tspan fill="#
|
|
57
|
-
<tspan fill="#
|
|
58
|
-
<tspan fill="#
|
|
59
|
-
<tspan fill="#a7c080">In 2d </tspan>
|
|
60
|
-
<tspan fill="#7a8478">Today 10:02</tspan>
|
|
51
|
+
<tspan fill="#859289">College 重构前置查阅外部架构参考库 </tspan>
|
|
52
|
+
<tspan fill="#7a8478">College/优化 · notes.md </tspan>
|
|
53
|
+
<tspan fill="#56635f">8d ago · quiet</tspan>
|
|
61
54
|
</text>
|
|
62
55
|
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<tspan fill="#859289">College 重构前置查阅外部架构参考库 </tspan>
|
|
67
|
-
<tspan fill="#7a8478"> College/优化 </tspan>
|
|
68
|
-
<tspan fill="#7a8478">Quiet (0 tok) </tspan>
|
|
69
|
-
<tspan fill="#56635f">09-28 14:20</tspan>
|
|
70
|
-
</text>
|
|
71
|
-
|
|
72
|
-
<rect x="45" y="274" width="750" height="58" rx="6" fill="#232a2e" stroke="#3a464c" stroke-width="1" />
|
|
73
|
-
<text x="62" y="298" fill="#a7c080" font-weight="bold">⚡ 会话内实时自主核销(执行 git commit 或测试通过当场自动结案):</text>
|
|
74
|
-
<text x="62" y="319" fill="#d3c6aa"> git commit -m "feat(auth): 重构鉴权模块为 HttpOnly Cookie" ➔ ⌖ Auto-settled #anc-1</text>
|
|
56
|
+
<rect x="45" y="242" width="750" height="58" rx="6" fill="#232a2e" stroke="#3a464c" stroke-width="1" />
|
|
57
|
+
<text x="62" y="266" fill="#dbbc7f">1. 随手贴一张: /pin 把 src/auth.ts 的登录改用 HttpOnly Cookie</text>
|
|
58
|
+
<text x="62" y="287" fill="#a7c080">2. 提交自动撕: git commit -m "feat: 登录改用 HttpOnly Cookie" ➔ ⌖ Torn off #1</text>
|
|
75
59
|
|
|
76
|
-
<text x="45" y="
|
|
60
|
+
<text x="45" y="334" fill="#7a8478">
|
|
77
61
|
<tspan> 常用命令: </tspan>
|
|
78
|
-
<tspan fill="#7fbbb3" font-weight="bold">`/pin <
|
|
62
|
+
<tspan fill="#7fbbb3" font-weight="bold">`/pin <便签>`</tspan>
|
|
79
63
|
<tspan> · </tspan>
|
|
80
64
|
<tspan fill="#7fbbb3" font-weight="bold">`/anchor`</tspan>
|
|
81
65
|
<tspan> · </tspan>
|
package/bin/anchor.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Anchor CLI
|
|
5
|
-
* Production-ready executable with dual-timeline & 4-quadrant cognitive grouping
|
|
4
|
+
* Anchor CLI — Minimalist terminal sticky notes for AI coding
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
import {
|
|
9
8
|
AnchorStore,
|
|
10
9
|
formatOrigin,
|
|
11
|
-
|
|
12
|
-
formatCreationTime,
|
|
10
|
+
formatRelativeAge,
|
|
13
11
|
sortAnchorsForDisplay,
|
|
14
12
|
padToWidth
|
|
15
13
|
} from '../dist/index.js';
|
|
@@ -17,55 +15,43 @@ import {
|
|
|
17
15
|
const store = new AnchorStore();
|
|
18
16
|
const args = process.argv.slice(2);
|
|
19
17
|
|
|
20
|
-
// 1. View
|
|
18
|
+
// 1. View sticky notes: `anchor` or `anchor list`
|
|
21
19
|
if (args.length === 0 || args[0] === 'list' || args[0] === 'ls') {
|
|
22
|
-
const
|
|
20
|
+
const allNotes = store
|
|
23
21
|
.list({ cwd: process.cwd(), all: true })
|
|
24
22
|
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
25
23
|
|
|
26
|
-
if (
|
|
27
|
-
console.log('\n⌖ No
|
|
24
|
+
if (allNotes.length === 0) {
|
|
25
|
+
console.log('\n⌖ No sticky notes. Run `anchor "<note>"` to stick one.\n');
|
|
28
26
|
process.exit(0);
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
const sorted = sortAnchorsForDisplay(
|
|
32
|
-
|
|
33
|
-
const quietCount = sorted.length - activeCount;
|
|
34
|
-
const headerSuffix = quietCount > 0 ? `${activeCount} active, ${quietCount} quiet` : `${activeCount} active`;
|
|
35
|
-
|
|
36
|
-
console.log(`\n⌖ Anchors (${headerSuffix}):\n`);
|
|
29
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
30
|
+
console.log(`\n⌖ Notes (${sorted.length}):\n`);
|
|
37
31
|
|
|
38
32
|
sorted.forEach((a, idx) => {
|
|
39
33
|
const num = String(idx + 1).padStart(2, '0');
|
|
40
|
-
const badge = a.status === 'sleeping'
|
|
41
|
-
? padToWidth('[Quiet]', 10)
|
|
42
|
-
: padToWidth(`[${a.priority.toUpperCase()}]`, 10);
|
|
43
34
|
const origin = formatOrigin(a);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const titleWithFiles = (a.files && a.files.length > 0)
|
|
48
|
-
? `${a.title} [${a.files.slice(0, 1).join(', ')}]`
|
|
49
|
-
: a.title;
|
|
35
|
+
const age = a.status === 'sleeping'
|
|
36
|
+
? `${formatRelativeAge(a.createdAt)} · quiet`
|
|
37
|
+
: formatRelativeAge(a.createdAt);
|
|
50
38
|
|
|
51
39
|
const colNum = ` ${num} `;
|
|
52
|
-
const colTitle = padToWidth(
|
|
53
|
-
const colOrigin = padToWidth(origin,
|
|
54
|
-
const colTarget = padToWidth(target, 14);
|
|
55
|
-
const colCreated = created;
|
|
40
|
+
const colTitle = padToWidth(a.title, 42);
|
|
41
|
+
const colOrigin = padToWidth(origin, 22);
|
|
56
42
|
|
|
57
|
-
console.log(`${colNum}${
|
|
43
|
+
console.log(`${colNum}${colTitle} ${colOrigin} ${age}`);
|
|
58
44
|
});
|
|
59
45
|
|
|
60
|
-
console.log('\n
|
|
46
|
+
console.log('\n Run `anchor done <num>` to tear off, or `anchor undo` to put back.\n');
|
|
61
47
|
process.exit(0);
|
|
62
48
|
}
|
|
63
49
|
|
|
64
|
-
// 2.
|
|
50
|
+
// 2. Put back last torn-off note: `anchor undo`
|
|
65
51
|
if (args[0] === 'undo') {
|
|
66
52
|
try {
|
|
67
53
|
const restored = store.undoSettle();
|
|
68
|
-
console.log(`⌖
|
|
54
|
+
console.log(`⌖ Put back #${restored.id.replace(/^anc-/, '')}: "${restored.title}"`);
|
|
69
55
|
} catch (err) {
|
|
70
56
|
console.error(`Error: ${err.message}`);
|
|
71
57
|
process.exit(1);
|
|
@@ -73,53 +59,43 @@ if (args[0] === 'undo') {
|
|
|
73
59
|
process.exit(0);
|
|
74
60
|
}
|
|
75
61
|
|
|
76
|
-
// 3. Help: `anchor --help`
|
|
62
|
+
// 3. Help: `anchor --help`
|
|
77
63
|
if (args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
|
|
78
64
|
console.log(`
|
|
79
|
-
⌖ Anchor
|
|
65
|
+
⌖ Anchor — Digital sticky notes for AI coding sessions
|
|
80
66
|
|
|
81
67
|
Usage:
|
|
82
|
-
anchor
|
|
83
|
-
anchor <
|
|
84
|
-
anchor done <
|
|
85
|
-
anchor undo
|
|
86
|
-
|
|
87
|
-
Options:
|
|
88
|
-
-h, --help Show this help message
|
|
89
|
-
-v, --version Show version
|
|
90
|
-
-d, --due <date> Specify expected completion date (e.g. tomorrow, friday, 2026-09-28)
|
|
68
|
+
anchor View all sticky notes
|
|
69
|
+
anchor "<note>" Stick a new note
|
|
70
|
+
anchor done <num> Tear off a completed note (e.g. anchor done 1)
|
|
71
|
+
anchor undo Put back the last torn-off note
|
|
91
72
|
`);
|
|
92
73
|
process.exit(0);
|
|
93
74
|
}
|
|
94
75
|
|
|
95
|
-
// 4.
|
|
76
|
+
// 4. Tear off note: `anchor done <num>`
|
|
96
77
|
if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
|
|
97
78
|
const idInput = args[1];
|
|
98
79
|
if (!idInput) {
|
|
99
|
-
console.error('Usage: anchor done <
|
|
80
|
+
console.error('Usage: anchor done <num>');
|
|
100
81
|
process.exit(1);
|
|
101
82
|
}
|
|
102
83
|
try {
|
|
103
|
-
|
|
104
|
-
const allUnfinished = store
|
|
84
|
+
const allNotes = store
|
|
105
85
|
.list({ cwd: process.cwd(), all: true })
|
|
106
86
|
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
107
|
-
const
|
|
87
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
108
88
|
|
|
109
89
|
let targetId = idInput;
|
|
110
|
-
|
|
111
|
-
if (numMatch) {
|
|
90
|
+
if (/^\d+$/.test(idInput)) {
|
|
112
91
|
const seqIndex = parseInt(idInput, 10);
|
|
113
|
-
if (seqIndex >= 1 && seqIndex <=
|
|
114
|
-
targetId =
|
|
92
|
+
if (seqIndex >= 1 && seqIndex <= sorted.length) {
|
|
93
|
+
targetId = sorted[seqIndex - 1].id;
|
|
115
94
|
}
|
|
116
95
|
}
|
|
117
96
|
|
|
118
|
-
const settled = store.settle(targetId, { settledBy: 'manual
|
|
119
|
-
|
|
120
|
-
? `⌖ Completed for today: "${settled.title}" (resets tomorrow)`
|
|
121
|
-
: `⌖ Settled: "${settled.title}"`;
|
|
122
|
-
console.log(successMsg);
|
|
97
|
+
const settled = store.settle(targetId, { settledBy: 'manual' });
|
|
98
|
+
console.log(`⌖ Torn off: "${settled.title}"`);
|
|
123
99
|
} catch (err) {
|
|
124
100
|
console.error(`Error: ${err.message}`);
|
|
125
101
|
process.exit(1);
|
|
@@ -127,24 +103,15 @@ if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
|
|
|
127
103
|
process.exit(0);
|
|
128
104
|
}
|
|
129
105
|
|
|
130
|
-
// 5.
|
|
131
|
-
let targetDateFlag;
|
|
132
|
-
const dueIdx = args.findIndex(a => a === '--due' || a === '-d');
|
|
133
|
-
if (dueIdx !== -1 && args[dueIdx + 1]) {
|
|
134
|
-
targetDateFlag = args[dueIdx + 1];
|
|
135
|
-
args.splice(dueIdx, 2);
|
|
136
|
-
}
|
|
137
|
-
|
|
106
|
+
// 5. Stick a new note: `anchor <note text>`
|
|
138
107
|
const title = args.join(' ').trim();
|
|
139
108
|
if (!title) {
|
|
140
|
-
console.error('Error:
|
|
109
|
+
console.error('Error: Note text cannot be empty');
|
|
141
110
|
process.exit(1);
|
|
142
111
|
}
|
|
143
112
|
|
|
144
|
-
const
|
|
113
|
+
const created = store.create({
|
|
145
114
|
title,
|
|
146
|
-
targetDate: targetDateFlag,
|
|
147
115
|
cwd: process.cwd()
|
|
148
116
|
});
|
|
149
|
-
|
|
150
|
-
console.log(`⌖ Pinned #${anc.id}: "${anc.title}" [${anc.project}]${targetBadge}`);
|
|
117
|
+
console.log(`⌖ Pinned #${created.id.replace(/^anc-/, '')}: "${created.title}"`);
|