@askdkc/kiokuko 0.1.2 → 0.1.4
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.ja.md +17 -11
- package/README.ko.md +17 -11
- package/README.md +29 -12
- package/README.zh-CN.md +17 -11
- package/dist/agent-file/render.d.ts +1 -1
- package/dist/agent-file/render.d.ts.map +1 -1
- package/dist/agent-file/render.js +7 -5
- package/dist/agent-file/render.js.map +1 -1
- package/dist/bin/kiokuko.js +11 -4
- package/dist/bin/kiokuko.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +19 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/setup.d.ts +3 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +8 -2
- package/dist/commands/setup.js.map +1 -1
- package/dist/config/paths.d.ts +1 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +5 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +4 -2
- package/dist/db/connection.js.map +1 -1
- package/dist/db/migrate.d.ts +7 -0
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +76 -4
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/upgrade-backup.d.ts +3 -0
- package/dist/db/upgrade-backup.d.ts.map +1 -0
- package/dist/db/upgrade-backup.js +43 -0
- package/dist/db/upgrade-backup.js.map +1 -0
- package/dist/mcp/server.js +3 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/runtime-version.d.ts +5 -0
- package/dist/runtime-version.d.ts.map +1 -0
- package/dist/runtime-version.js +16 -0
- package/dist/runtime-version.js.map +1 -0
- package/dist/setup/opencode-loop-guard.d.ts +4 -0
- package/dist/setup/opencode-loop-guard.d.ts.map +1 -0
- package/dist/setup/opencode-loop-guard.js +168 -0
- package/dist/setup/opencode-loop-guard.js.map +1 -0
- package/dist/setup/render.d.ts.map +1 -1
- package/dist/setup/render.js +7 -5
- package/dist/setup/render.js.map +1 -1
- package/dist/web/i18n.d.ts +83 -0
- package/dist/web/i18n.d.ts.map +1 -0
- package/dist/web/i18n.js +329 -0
- package/dist/web/i18n.js.map +1 -0
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +196 -65
- package/dist/web/ui.js.map +1 -1
- package/package.json +3 -3
- package/templates/AGENTS.md +7 -5
package/dist/web/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,QAAQ,QAoYb,CAAC"}
|
package/dist/web/ui.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
+
import { DEFAULT_WEB_LOCALE, WEB_LOCALE_LABELS, WEB_LOCALES, WEB_MESSAGES } from './i18n.js';
|
|
2
|
+
const WEB_I18N_CONFIG = JSON.stringify({
|
|
3
|
+
defaultLocale: DEFAULT_WEB_LOCALE,
|
|
4
|
+
localeLabels: WEB_LOCALE_LABELS,
|
|
5
|
+
locales: WEB_LOCALES,
|
|
6
|
+
messages: WEB_MESSAGES,
|
|
7
|
+
})
|
|
8
|
+
.replaceAll('&', '\\u0026')
|
|
9
|
+
.replaceAll('<', '\\u003c')
|
|
10
|
+
.replaceAll('>', '\\u003e')
|
|
11
|
+
.replaceAll('\u2028', '\\u2028')
|
|
12
|
+
.replaceAll('\u2029', '\\u2029');
|
|
1
13
|
export const WEB_HTML = String.raw `<!doctype html>
|
|
2
|
-
<html lang="
|
|
14
|
+
<html lang="en">
|
|
3
15
|
<head>
|
|
4
16
|
<meta charset="utf-8">
|
|
5
17
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
@@ -7,15 +19,29 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
7
19
|
<style>
|
|
8
20
|
:root { color-scheme: light; --ink:#1e293b; --muted:#64748b; --line:#e2e8f0; --panel:#ffffff; --surface:#f8fafc; --accent:#2563eb; --accent-soft:#eff6ff; --warn:#b45309; --danger:#b91c1c; }
|
|
9
21
|
* { box-sizing:border-box; }
|
|
22
|
+
[hidden] { display:none !important; }
|
|
10
23
|
body { margin:0; background:linear-gradient(135deg,#f8fafc,#eef2ff); color:var(--ink); font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; }
|
|
11
24
|
button,input,select,textarea { font:inherit; }
|
|
12
25
|
button { cursor:pointer; }
|
|
13
26
|
.shell { max-width:1440px; margin:0 auto; padding:28px; }
|
|
14
|
-
.topbar { display:
|
|
27
|
+
.topbar { display:grid; grid-template-columns:minmax(0,1.1fr) minmax(420px,.9fr); gap:24px; align-items:start; margin-bottom:22px; }
|
|
28
|
+
.brand,.topbar-side { min-width:0; }
|
|
29
|
+
.topbar-side { display:flex; flex-direction:column; gap:10px; align-self:stretch; }
|
|
15
30
|
.eyebrow { color:var(--accent); font-size:12px; font-weight:800; letter-spacing:.16em; text-transform:uppercase; }
|
|
16
31
|
h1 { margin:4px 0 0; font-size:clamp(28px,4vw,44px); letter-spacing:-.04em; }
|
|
17
32
|
.subtitle { margin:8px 0 0; color:var(--muted); }
|
|
18
|
-
.
|
|
33
|
+
.language-picker { position:relative; align-self:flex-end; z-index:10; }
|
|
34
|
+
.language-toggle { display:grid; place-items:center; width:44px; height:44px; border:1px solid var(--line); border-radius:12px; background:var(--panel); color:var(--ink); box-shadow:0 6px 18px rgba(15,23,42,.06); }
|
|
35
|
+
.language-toggle:hover,.language-toggle[aria-expanded="true"] { border-color:#93c5fd; background:var(--accent-soft); color:var(--accent); }
|
|
36
|
+
.language-toggle:focus-visible,.language-option:focus-visible { outline:3px solid rgba(37,99,235,.25); outline-offset:2px; }
|
|
37
|
+
.language-toggle svg { width:22px; height:22px; }
|
|
38
|
+
.language-menu { position:absolute; top:calc(100% + 8px); right:0; display:grid; gap:2px; width:max-content; min-width:168px; padding:6px; border:1px solid var(--line); border-radius:14px; background:var(--panel); box-shadow:0 18px 48px rgba(15,23,42,.16); }
|
|
39
|
+
.language-option { display:flex; align-items:center; justify-content:space-between; gap:18px; width:100%; border:0; border-radius:9px; padding:9px 11px; background:transparent; color:var(--ink); text-align:left; }
|
|
40
|
+
.language-option:hover,.language-option:focus-visible,.language-option[aria-checked="true"] { background:var(--accent-soft); color:var(--accent); }
|
|
41
|
+
.language-option[aria-checked="true"]::after { content:"✓"; font-weight:800; }
|
|
42
|
+
.toolbar { display:flex; gap:10px; align-items:center; justify-content:flex-end; flex-wrap:wrap; margin-top:auto; }
|
|
43
|
+
.topbar-side .control { flex:1 1 210px; width:auto; min-width:0; }
|
|
44
|
+
.topbar-side .search { flex:1.4 1 240px; width:auto; min-width:0; }
|
|
19
45
|
.control, .search { border:1px solid var(--line); border-radius:12px; background:var(--panel); color:var(--ink); padding:10px 12px; }
|
|
20
46
|
.search { min-width:260px; }
|
|
21
47
|
.button { border:1px solid var(--line); border-radius:12px; background:var(--panel); color:var(--ink); padding:10px 14px; font-weight:700; }
|
|
@@ -56,7 +82,7 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
56
82
|
.notice { border-radius:12px; padding:11px 12px; background:#fffbeb; color:var(--warn); font-size:13px; }
|
|
57
83
|
.notice.error { background:#fef2f2; color:var(--danger); }
|
|
58
84
|
.status { color:var(--muted); font-size:12px; min-height:18px; }
|
|
59
|
-
.operator-panel { grid-column:1 / -1; }
|
|
85
|
+
.operator-panel { grid-column:1 / -1; margin-top:16px; }
|
|
60
86
|
.operator-grid { display:grid; grid-template-columns:minmax(240px,.7fr) minmax(420px,1.3fr); gap:16px; }
|
|
61
87
|
.run-list { display:flex; flex-direction:column; gap:8px; max-height:360px; overflow:auto; }
|
|
62
88
|
.run-card { border:1px solid var(--line); border-radius:12px; padding:11px; background:var(--panel); text-align:left; }
|
|
@@ -66,63 +92,146 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
66
92
|
.detail-text { white-space:pre-wrap; overflow-wrap:anywhere; color:var(--muted); font-size:13px; }
|
|
67
93
|
@media (max-width:680px) { .operator-grid { grid-template-columns:1fr; } }
|
|
68
94
|
@media (max-width:1050px) { .layout { grid-template-columns:180px minmax(280px,1fr); } .editor-panel { grid-column:1 / -1; } }
|
|
69
|
-
@media (max-width:680px) { .shell { padding:16px; } .topbar { display:block; } .
|
|
95
|
+
@media (max-width:680px) { .shell { padding:16px; } .topbar { display:block; position:relative; } .brand { padding-right:56px; } .topbar-side { margin-top:16px; align-self:auto; } .language-picker { position:absolute; top:0; right:0; } .toolbar { justify-content:stretch; margin-top:0; } .topbar-side .control,.topbar-side .search { flex:1 1 100%; width:100%; } .search { min-width:0; } .layout { grid-template-columns:1fr; } .genres-panel { order:0; } .list-panel { order:1; } .editor-panel { order:2; } .entry-list { max-height:none; } }
|
|
70
96
|
</style>
|
|
71
97
|
</head>
|
|
72
98
|
<body>
|
|
73
99
|
<main class="shell">
|
|
74
100
|
<header class="topbar">
|
|
75
|
-
<div>
|
|
76
|
-
<div class="eyebrow">Local memory console</div>
|
|
101
|
+
<div class="brand">
|
|
102
|
+
<div class="eyebrow" data-i18n="eyebrow">Local memory console</div>
|
|
77
103
|
<h1>Kiokuko Web</h1>
|
|
78
|
-
<p class="subtitle">
|
|
104
|
+
<p class="subtitle" data-i18n="subtitle">Browse SQLite memory by role and purpose, memory type, and cross-cutting tags, and safely edit candidate entries.</p>
|
|
79
105
|
</div>
|
|
80
|
-
<div class="
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
106
|
+
<div class="topbar-side">
|
|
107
|
+
<div id="language-picker" class="language-picker">
|
|
108
|
+
<button id="language-toggle" class="language-toggle" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="language-menu" aria-label="Language" data-i18n-aria-label="languageLabel">
|
|
109
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"></circle><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"></path></svg>
|
|
110
|
+
</button>
|
|
111
|
+
<div id="language-menu" class="language-menu" role="menu" aria-label="Language" data-i18n-aria-label="languageLabel" hidden></div>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="toolbar">
|
|
114
|
+
<select id="workspace" class="control" aria-label="Workspace" data-i18n-aria-label="workspaceLabel"></select>
|
|
115
|
+
<input id="search" class="search" type="search" placeholder="Search memory…" aria-label="Search memory…" data-i18n-placeholder="searchPlaceholder" data-i18n-aria-label="searchPlaceholder">
|
|
116
|
+
<button id="refresh" class="button" type="button" data-i18n="refresh">Refresh</button>
|
|
117
|
+
</div>
|
|
84
118
|
</div>
|
|
85
119
|
</header>
|
|
86
120
|
<div id="status" class="status" role="status"></div>
|
|
87
121
|
<section class="layout">
|
|
88
122
|
<aside class="panel genres-panel">
|
|
89
|
-
<div class="panel-head"><h2>
|
|
90
|
-
<nav id="genres" class="genres" aria-label="
|
|
123
|
+
<div class="panel-head"><h2 data-i18n="filtersPanelTitle">Role and purpose / tags</h2></div>
|
|
124
|
+
<nav id="genres" class="genres" aria-label="Filter by role and purpose, memory type, or tag" data-i18n-aria-label="filtersNavLabel"></nav>
|
|
91
125
|
</aside>
|
|
92
126
|
<section class="panel list-panel">
|
|
93
|
-
<div class="panel-head"><h2 id="list-title"
|
|
127
|
+
<div class="panel-head"><h2 id="list-title">Memory</h2><span id="result-count" class="badge">0 items</span></div>
|
|
94
128
|
<div class="panel-body"><div id="entry-list" class="entry-list"></div></div>
|
|
95
129
|
</section>
|
|
96
130
|
<section class="panel editor-panel">
|
|
97
|
-
<div class="panel-head"><h2
|
|
131
|
+
<div class="panel-head"><h2 data-i18n="editorTitle">Details</h2><span id="editor-state" class="badge" data-i18n="unselected">Not selected</span></div>
|
|
98
132
|
<div class="panel-body"><div id="editor"></div></div>
|
|
99
133
|
</section>
|
|
100
134
|
</section>
|
|
101
135
|
<section class="panel operator-panel">
|
|
102
|
-
<div class="panel-head"><h2>Agent run operator view</h2><span class="badge">stored data is untrusted / non-actionable</span></div>
|
|
136
|
+
<div class="panel-head"><h2 data-i18n="operatorTitle">Agent run operator view</h2><span class="badge" data-i18n="trustBadge">stored data is untrusted / non-actionable</span></div>
|
|
103
137
|
<div class="panel-body operator-grid">
|
|
104
138
|
<div><div id="run-list" class="run-list"></div><div id="run-page" class="status"></div></div>
|
|
105
|
-
<div id="run-detail"><div class="editor-empty">run
|
|
139
|
+
<div id="run-detail"><div class="editor-empty" data-i18n="runSelectFull">Select a run to view its intake, profile, timeline, delivery, feedback, and coverage.</div></div>
|
|
106
140
|
</div>
|
|
107
141
|
</section>
|
|
108
142
|
</main>
|
|
109
143
|
<script>
|
|
144
|
+
const i18n = ${WEB_I18N_CONFIG};
|
|
145
|
+
const localeStorageKey = 'kiokuko.web.locale';
|
|
146
|
+
const normalizeLocale = (value) => {
|
|
147
|
+
if (typeof value !== 'string') return null;
|
|
148
|
+
const normalized = value.trim().replaceAll('_', '-').toLowerCase();
|
|
149
|
+
if (!normalized) return null;
|
|
150
|
+
const parts = normalized.split('-');
|
|
151
|
+
const language = parts[0];
|
|
152
|
+
if (language === 'en' || language === 'ja' || language === 'ko') return language;
|
|
153
|
+
if (language === 'zh' && (parts.length === 1 || parts.includes('hans') || parts.includes('cn') || parts.includes('sg'))) return 'zh-CN';
|
|
154
|
+
return null;
|
|
155
|
+
};
|
|
156
|
+
const readStoredLocale = () => { try { return localStorage.getItem(localeStorageKey); } catch { return null; } };
|
|
157
|
+
const browserLocales = Array.isArray(navigator.languages) ? navigator.languages : [navigator.language];
|
|
158
|
+
const localeCandidates = [new URLSearchParams(location.search).get('lang'), readStoredLocale(), ...browserLocales];
|
|
159
|
+
const initialLocale = localeCandidates.map(normalizeLocale).find(Boolean) || i18n.defaultLocale;
|
|
110
160
|
const kinds = [
|
|
111
|
-
['all', '
|
|
161
|
+
['all', 'kind.all'], ['fact', 'kind.fact'], ['decision', 'kind.decision'], ['lesson', 'kind.lesson'], ['preference', 'kind.preference'], ['reference', 'kind.reference']
|
|
112
162
|
];
|
|
113
163
|
const botModes = [
|
|
114
|
-
['bot:common', '
|
|
164
|
+
['bot:common', 'bot.common'], ['bot:researcher', 'bot.researcher'], ['bot:builder', 'bot.builder'], ['bot:reviewer', 'bot.reviewer'], ['bot:devops', 'bot.devops'], ['bot:writer', 'bot.writer'], ['bot:analyst', 'bot.analyst']
|
|
115
165
|
];
|
|
116
|
-
const state = { workspace: '', kind: 'all', tag: '', query: '', entries: [], tags: [], selected: null, runs: [], selectedRun: null };
|
|
166
|
+
const state = { locale: initialLocale, workspace: '', kind: 'all', tag: '', query: '', entries: [], tags: [], selected: null, runs: [], selectedRun: null, localizedStatus: null };
|
|
117
167
|
const $ = (id) => document.getElementById(id);
|
|
168
|
+
const t = (key, parameters = {}) => {
|
|
169
|
+
const template = i18n.messages[state.locale]?.[key] ?? i18n.messages[i18n.defaultLocale]?.[key] ?? key;
|
|
170
|
+
return template.replace(/\{([^}]+)\}/g, (_match, name) => Object.prototype.hasOwnProperty.call(parameters, name) ? String(parameters[name]) : '');
|
|
171
|
+
};
|
|
172
|
+
const tp = (key, count) => {
|
|
173
|
+
const category = new Intl.PluralRules(state.locale).select(count) === 'one' ? 'one' : 'other';
|
|
174
|
+
return t(key + '.' + category, { count });
|
|
175
|
+
};
|
|
176
|
+
const setI18nText = (element, key) => { element.dataset.i18n = key; element.textContent = t(key); return element; };
|
|
177
|
+
const labelForKind = (kind) => { const item = kinds.find(([value]) => value === kind); return item ? t(item[1]) : kind; };
|
|
178
|
+
const labelForStatus = (status) => i18n.messages[state.locale]?.['status.' + status] ?? status;
|
|
179
|
+
const updateEditorState = () => {
|
|
180
|
+
const element = $('editor-state');
|
|
181
|
+
if (state.selected) { delete element.dataset.i18n; element.dataset.i18nStatus = state.selected.status; element.textContent = labelForStatus(state.selected.status); }
|
|
182
|
+
else { delete element.dataset.i18nStatus; setI18nText(element, 'unselected'); }
|
|
183
|
+
};
|
|
184
|
+
const showStatus = (message, error = false) => { $('status').textContent = message; $('status').className = error ? 'status notice error' : 'status'; };
|
|
185
|
+
const setStatus = (message, error = false) => { state.localizedStatus = null; showStatus(message, error); };
|
|
186
|
+
const setLocalizedStatus = (key, parameters = {}, error = false) => { state.localizedStatus = { key, parameters, error }; showStatus(t(key, parameters), error); };
|
|
187
|
+
const setLocalizedCountStatus = (key, count, error = false) => { state.localizedStatus = { key, count, error, plural: true }; showStatus(tp(key, count), error); };
|
|
188
|
+
const renderLanguageMenu = () => {
|
|
189
|
+
const menu = $('language-menu');
|
|
190
|
+
menu.replaceChildren(...i18n.locales.map((locale) => {
|
|
191
|
+
const option = document.createElement('button');
|
|
192
|
+
option.type = 'button';
|
|
193
|
+
option.className = 'language-option';
|
|
194
|
+
option.lang = locale;
|
|
195
|
+
option.dataset.locale = locale;
|
|
196
|
+
option.setAttribute('role', 'menuitemradio');
|
|
197
|
+
option.setAttribute('aria-checked', String(locale === state.locale));
|
|
198
|
+
option.textContent = i18n.localeLabels[locale];
|
|
199
|
+
option.addEventListener('click', () => selectLocale(locale));
|
|
200
|
+
return option;
|
|
201
|
+
}));
|
|
202
|
+
};
|
|
203
|
+
const setLanguageMenuOpen = (open, restoreFocus = false) => {
|
|
204
|
+
const menu = $('language-menu');
|
|
205
|
+
const toggle = $('language-toggle');
|
|
206
|
+
menu.hidden = !open;
|
|
207
|
+
toggle.setAttribute('aria-expanded', String(open));
|
|
208
|
+
if (open) requestAnimationFrame(() => menu.querySelector('[aria-checked="true"]')?.focus());
|
|
209
|
+
else if (restoreFocus) toggle.focus();
|
|
210
|
+
};
|
|
211
|
+
const selectLocale = (value) => {
|
|
212
|
+
state.locale = normalizeLocale(value) || i18n.defaultLocale;
|
|
213
|
+
try { localStorage.setItem(localeStorageKey, state.locale); } catch {}
|
|
214
|
+
setLanguageMenuOpen(false, true);
|
|
215
|
+
applyTranslations(); renderFilters(); renderEntries(); renderRuns(); renderRunDetail(); updateEditorState();
|
|
216
|
+
};
|
|
217
|
+
const applyTranslations = () => {
|
|
218
|
+
document.documentElement.lang = state.locale;
|
|
219
|
+
document.querySelectorAll('[data-i18n]').forEach((element) => { element.textContent = t(element.dataset.i18n); });
|
|
220
|
+
document.querySelectorAll('[data-i18n-aria-label]').forEach((element) => { element.setAttribute('aria-label', t(element.dataset.i18nAriaLabel)); });
|
|
221
|
+
document.querySelectorAll('[data-i18n-placeholder]').forEach((element) => { element.setAttribute('placeholder', t(element.dataset.i18nPlaceholder)); });
|
|
222
|
+
document.querySelectorAll('[data-i18n-status]').forEach((element) => {
|
|
223
|
+
const value = labelForStatus(element.dataset.i18nStatus);
|
|
224
|
+
if ('value' in element) element.value = value; else element.textContent = value;
|
|
225
|
+
});
|
|
226
|
+
renderLanguageMenu();
|
|
227
|
+
if (state.localizedStatus) showStatus(state.localizedStatus.plural ? tp(state.localizedStatus.key, state.localizedStatus.count) : t(state.localizedStatus.key, state.localizedStatus.parameters), state.localizedStatus.error);
|
|
228
|
+
};
|
|
118
229
|
const api = async (path, options) => {
|
|
119
230
|
const response = await fetch(path, options);
|
|
120
231
|
const value = await response.json();
|
|
121
|
-
if (!response.ok) throw new Error(value.error?.message || '
|
|
232
|
+
if (!response.ok) throw new Error(value.error?.message || t('requestFailed'));
|
|
122
233
|
return value;
|
|
123
234
|
};
|
|
124
|
-
const setStatus = (message, error = false) => { $('status').textContent = message; $('status').className = error ? 'status notice error' : 'status'; };
|
|
125
|
-
const labelForKind = (kind) => (kinds.find((item) => item[0] === kind) || [kind, kind])[1];
|
|
126
235
|
const escapeTags = (value) => value.split(',').map((item) => item.trim()).filter(Boolean);
|
|
127
236
|
|
|
128
237
|
function filterButton(key, label, count, active, onClick) {
|
|
@@ -145,32 +254,32 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
145
254
|
function renderFilters() {
|
|
146
255
|
const kindCounts = Object.fromEntries(kinds.map(([kind]) => [kind, kind === 'all' ? state.entries.length : state.entries.filter((entry) => entry.kind === kind).length]));
|
|
147
256
|
const tagCounts = Object.fromEntries(state.tags.map((item) => [item.tag, item.count]));
|
|
148
|
-
const botButtons = botModes.map(([tag, label]) => filterButton(tag, label, tagCounts[tag], state.tag === tag, () => { state.tag = tag; renderFilters(); loadEntries(); }));
|
|
149
|
-
const kindButtons = kinds.map(([kind, label]) => filterButton(kind, label, kindCounts[kind], state.kind === kind, () => { state.kind = kind; renderFilters(); loadEntries(); }));
|
|
257
|
+
const botButtons = botModes.map(([tag, label]) => filterButton(tag, t(label), tagCounts[tag], state.tag === tag, () => { state.tag = tag; renderFilters(); loadEntries(); }));
|
|
258
|
+
const kindButtons = kinds.map(([kind, label]) => filterButton(kind, t(label), kindCounts[kind], state.kind === kind, () => { state.kind = kind; renderFilters(); loadEntries(); }));
|
|
150
259
|
const tagButtons = state.tags
|
|
151
260
|
.filter((item) => !botModes.some(([tag]) => tag === item.tag))
|
|
152
261
|
.map((item) => filterButton(item.tag, '#' + item.tag, item.count, state.tag === item.tag, () => { state.tag = item.tag; renderFilters(); loadEntries(); }));
|
|
153
|
-
const root = $('genres'); root.replaceChildren(filterGroup('
|
|
154
|
-
if (tagButtons.length > 0) root.append(filterGroup('
|
|
262
|
+
const root = $('genres'); root.replaceChildren(filterGroup(t('botFilterTitle'), botButtons), filterGroup(t('memoryTypeFilterTitle'), kindButtons));
|
|
263
|
+
if (tagButtons.length > 0) root.append(filterGroup(t('crossTagFilterTitle'), tagButtons));
|
|
155
264
|
}
|
|
156
265
|
|
|
157
266
|
function renderEntries() {
|
|
158
|
-
$('result-count').textContent =
|
|
159
|
-
$('list-title').textContent = state.tag ? '#' + state.tag : (state.kind === 'all' ? '
|
|
267
|
+
$('result-count').textContent = tp('entryCount', state.entries.length);
|
|
268
|
+
$('list-title').textContent = state.tag ? '#' + state.tag : (state.kind === 'all' ? t('entriesTitle') : labelForKind(state.kind));
|
|
160
269
|
const list = $('entry-list');
|
|
161
270
|
if (!state.entries.length) {
|
|
162
|
-
const empty = document.createElement('div'); empty.className = 'editor-empty'; empty
|
|
271
|
+
const empty = document.createElement('div'); empty.className = 'editor-empty'; setI18nText(empty, 'noEntries'); list.replaceChildren(empty); return;
|
|
163
272
|
}
|
|
164
273
|
list.replaceChildren(...state.entries.map((entry) => {
|
|
165
274
|
const card = document.createElement('article'); card.className = 'entry-card ' + (state.selected?.id === entry.id ? 'selected' : '');
|
|
166
275
|
const meta = document.createElement('div'); meta.className = 'entry-meta';
|
|
167
276
|
const kind = document.createElement('span'); kind.className = 'badge'; kind.textContent = labelForKind(entry.kind);
|
|
168
|
-
const status = document.createElement('span'); status.className = 'badge ' + entry.status; status.textContent = entry.status;
|
|
169
|
-
const revision = document.createElement('span'); revision.textContent = 'revision ' + entry.revision; meta.append(kind, status, revision);
|
|
277
|
+
const status = document.createElement('span'); status.className = 'badge ' + entry.status; status.textContent = labelForStatus(entry.status);
|
|
278
|
+
const revision = document.createElement('span'); revision.textContent = t('revision') + ' ' + entry.revision; meta.append(kind, status, revision);
|
|
170
279
|
const title = document.createElement('h3'); title.textContent = entry.title;
|
|
171
280
|
const snippet = document.createElement('p'); snippet.className = 'snippet'; snippet.textContent = entry.summary || entry.body;
|
|
172
281
|
const tags = document.createElement('div'); tags.className = 'tags'; entry.tags.forEach((tag) => { const item = document.createElement('button'); item.type = 'button'; item.className = 'tag'; item.textContent = '#' + tag; item.addEventListener('click', (event) => { event.stopPropagation(); state.tag = tag; renderFilters(); loadEntries(); }); tags.append(item); });
|
|
173
|
-
const edit = document.createElement('button'); edit.type = 'button'; edit.className = 'button'; edit
|
|
282
|
+
const edit = document.createElement('button'); edit.type = 'button'; edit.className = 'button'; setI18nText(edit, 'edit'); edit.style.marginTop = '12px'; edit.addEventListener('click', (event) => { event.stopPropagation(); selectEntry(entry.id); });
|
|
174
283
|
card.append(meta, title, snippet, tags, edit); card.addEventListener('click', () => selectEntry(entry.id)); return card;
|
|
175
284
|
}));
|
|
176
285
|
}
|
|
@@ -178,27 +287,27 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
178
287
|
function renderEditor() {
|
|
179
288
|
const editor = $('editor');
|
|
180
289
|
const entry = state.selected;
|
|
181
|
-
|
|
182
|
-
if (!entry) { const empty = document.createElement('div'); empty.className = 'editor-empty'; empty
|
|
290
|
+
updateEditorState();
|
|
291
|
+
if (!entry) { const empty = document.createElement('div'); empty.className = 'editor-empty'; setI18nText(empty, 'selectMemory'); editor.replaceChildren(empty); return; }
|
|
183
292
|
const form = document.createElement('form'); form.className = 'form';
|
|
184
293
|
const row = document.createElement('div'); row.className = 'form-row';
|
|
185
|
-
const kindLabel = document.createElement('label');
|
|
186
|
-
const statusLabel = document.createElement('label');
|
|
187
|
-
const titleLabel = document.createElement('label');
|
|
188
|
-
const bodyLabel = document.createElement('label');
|
|
189
|
-
const summaryLabel = document.createElement('label');
|
|
190
|
-
const tagsLabel = document.createElement('label');
|
|
294
|
+
const kindLabel = document.createElement('label'); const kindLabelText = document.createElement('span'); setI18nText(kindLabelText, 'memoryType'); const kind = document.createElement('select'); kinds.filter(([value]) => value !== 'all').forEach(([value, label]) => { const option = document.createElement('option'); option.value = value; setI18nText(option, label); kind.append(option); }); kind.value = entry.kind; kindLabel.append(kindLabelText, kind);
|
|
295
|
+
const statusLabel = document.createElement('label'); const statusLabelText = document.createElement('span'); setI18nText(statusLabelText, 'status'); const status = document.createElement('input'); status.value = labelForStatus(entry.status); status.dataset.i18nStatus = entry.status; status.disabled = true; statusLabel.append(statusLabelText, status); row.append(kindLabel, statusLabel);
|
|
296
|
+
const titleLabel = document.createElement('label'); const titleLabelText = document.createElement('span'); setI18nText(titleLabelText, 'title'); const title = document.createElement('input'); title.value = entry.title; titleLabel.append(titleLabelText, title);
|
|
297
|
+
const bodyLabel = document.createElement('label'); const bodyLabelText = document.createElement('span'); setI18nText(bodyLabelText, 'body'); const body = document.createElement('textarea'); body.className = 'body'; body.value = entry.body; bodyLabel.append(bodyLabelText, body);
|
|
298
|
+
const summaryLabel = document.createElement('label'); const summaryLabelText = document.createElement('span'); setI18nText(summaryLabelText, 'summary'); const summary = document.createElement('textarea'); summary.value = entry.summary || ''; summaryLabel.append(summaryLabelText, summary);
|
|
299
|
+
const tagsLabel = document.createElement('label'); const tagsLabelText = document.createElement('span'); setI18nText(tagsLabelText, 'commaSeparatedTags'); const tags = document.createElement('input'); tags.value = entry.tags.join(', '); tagsLabel.append(tagsLabelText, tags);
|
|
191
300
|
const jsonRow = document.createElement('div'); jsonRow.className = 'form-row';
|
|
192
|
-
const scopeLabel = document.createElement('label');
|
|
193
|
-
const provenanceLabel = document.createElement('label');
|
|
301
|
+
const scopeLabel = document.createElement('label'); const scopeLabelText = document.createElement('span'); setI18nText(scopeLabelText, 'scopeJson'); const scope = document.createElement('textarea'); scope.value = JSON.stringify(entry.scope, null, 2); scopeLabel.append(scopeLabelText, scope);
|
|
302
|
+
const provenanceLabel = document.createElement('label'); const provenanceLabelText = document.createElement('span'); setI18nText(provenanceLabelText, 'provenanceJson'); const provenance = document.createElement('textarea'); provenance.value = JSON.stringify(entry.provenance, null, 2); provenanceLabel.append(provenanceLabelText, provenance); jsonRow.append(scopeLabel, provenanceLabel);
|
|
194
303
|
const actions = document.createElement('div'); actions.className = 'toolbar';
|
|
195
|
-
const save = document.createElement('button'); save.type = 'submit'; save.className = 'button primary'; save
|
|
196
|
-
const note = document.createElement('div'); note.className = entry.status === 'candidate' ? 'notice' : 'notice error'; note
|
|
304
|
+
const save = document.createElement('button'); save.type = 'submit'; save.className = 'button primary'; setI18nText(save, 'save');
|
|
305
|
+
const note = document.createElement('div'); note.className = entry.status === 'candidate' ? 'notice' : 'notice error'; setI18nText(note, entry.status === 'candidate' ? 'candidateNotice' : 'immutableNotice');
|
|
197
306
|
if (entry.status !== 'candidate') { save.disabled = true; [kind, title, body, summary, tags, scope, provenance].forEach((control) => { control.disabled = true; }); }
|
|
198
307
|
actions.append(save); form.append(row, titleLabel, bodyLabel, summaryLabel, tagsLabel, jsonRow, note, actions); form.addEventListener('submit', async (event) => { event.preventDefault(); if (save.disabled) return; try {
|
|
199
308
|
const payload = { expectedRevision: entry.revision, kind: kind.value, title: title.value, body: body.value, summary: summary.value || null, scope: JSON.parse(scope.value || '{}'), provenance: JSON.parse(provenance.value || '{}'), tags: escapeTags(tags.value) };
|
|
200
309
|
await api('/api/entries/' + encodeURIComponent(entry.id) + '?workspace=' + encodeURIComponent(state.workspace), { method: 'PUT', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) });
|
|
201
|
-
|
|
310
|
+
setLocalizedStatus('saved'); await loadEntries(); await selectEntry(entry.id);
|
|
202
311
|
} catch (error) { setStatus(error.message, true); }
|
|
203
312
|
}); editor.replaceChildren(form);
|
|
204
313
|
}
|
|
@@ -213,37 +322,37 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
213
322
|
} catch (error) { setStatus(error.message, true); }
|
|
214
323
|
}
|
|
215
324
|
|
|
216
|
-
function detailBlock(
|
|
325
|
+
function detailBlock(titleKey, value) {
|
|
217
326
|
const block = document.createElement('section'); block.className = 'detail-block';
|
|
218
|
-
const heading = document.createElement('h3'); heading
|
|
327
|
+
const heading = document.createElement('h3'); setI18nText(heading, titleKey);
|
|
219
328
|
const text = document.createElement('div'); text.className = 'detail-text'; text.textContent = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
220
329
|
block.append(heading, text); return block;
|
|
221
330
|
}
|
|
222
331
|
|
|
223
332
|
function renderRunDetail() {
|
|
224
333
|
const root = $('run-detail'); const detail = state.selectedRun;
|
|
225
|
-
if (!detail) { const empty = document.createElement('div'); empty.className = 'editor-empty'; empty
|
|
226
|
-
const heading = document.createElement('h3'); heading
|
|
334
|
+
if (!detail) { const empty = document.createElement('div'); empty.className = 'editor-empty'; setI18nText(empty, 'runSelect'); root.replaceChildren(empty); return; }
|
|
335
|
+
const heading = document.createElement('h3'); setI18nText(heading, 'contextWarning');
|
|
227
336
|
const blocks = [
|
|
228
|
-
detailBlock('
|
|
229
|
-
detailBlock('
|
|
230
|
-
detailBlock('
|
|
231
|
-
detailBlock('
|
|
232
|
-
detailBlock('
|
|
233
|
-
detailBlock('
|
|
234
|
-
detailBlock('
|
|
235
|
-
detailBlock('
|
|
236
|
-
detailBlock('
|
|
337
|
+
detailBlock('detailRunIntake', { run: detail.run, intake: detail.intake }),
|
|
338
|
+
detailBlock('detailInitialProfile', detail.profile.initial),
|
|
339
|
+
detailBlock('detailProjectedProfile', detail.profile.projected),
|
|
340
|
+
detailBlock('detailPolicySource', { policyVersion: detail.profile.policyVersion, source: detail.profile.source, initialProfileHash: detail.profile.initialProfileHash }),
|
|
341
|
+
detailBlock('detailCoverageWarnings', { coverage: detail.coverage, evidenceState: detail.evidenceState, warnings: detail.warnings }),
|
|
342
|
+
detailBlock('detailTimelineEvidence', { timeline: detail.timeline, evidence: detail.evidence }),
|
|
343
|
+
detailBlock('detailDeliveriesReasons', detail.deliveries),
|
|
344
|
+
detailBlock('detailFeedback', detail.feedback),
|
|
345
|
+
detailBlock('detailProposalLinks', { proposals: detail.proposals, links: detail.memoryLinks }),
|
|
237
346
|
];
|
|
238
347
|
root.replaceChildren(heading, ...blocks);
|
|
239
348
|
}
|
|
240
349
|
|
|
241
350
|
function renderRuns() {
|
|
242
351
|
const root = $('run-list');
|
|
243
|
-
if (!state.runs.length) { const empty = document.createElement('div'); empty.className = 'editor-empty'; empty
|
|
352
|
+
if (!state.runs.length) { const empty = document.createElement('div'); empty.className = 'editor-empty'; setI18nText(empty, 'noRuns'); root.replaceChildren(empty); return; }
|
|
244
353
|
root.replaceChildren(...state.runs.map((run) => {
|
|
245
354
|
const button = document.createElement('button'); button.type = 'button'; button.className = 'run-card' + (state.selectedRun?.run?.runId === run.runId ? ' selected' : '');
|
|
246
|
-
button.textContent = run.runId + ' / ' + (run.status || 'unknown') + ' / ' + (run.title || 'untitled');
|
|
355
|
+
button.textContent = run.runId + ' / ' + (run.status || t('unknown')) + ' / ' + (run.title || t('untitled'));
|
|
247
356
|
button.addEventListener('click', () => loadRunDetail(run.runId)); return button;
|
|
248
357
|
}));
|
|
249
358
|
}
|
|
@@ -252,18 +361,40 @@ export const WEB_HTML = String.raw `<!doctype html>
|
|
|
252
361
|
if (!state.workspace) return;
|
|
253
362
|
try {
|
|
254
363
|
const result = await api('/api/operator/runs?workspace=' + encodeURIComponent(state.workspace) + '&limit=50');
|
|
255
|
-
state.runs = result.items || []; renderRuns(); $('run-page')
|
|
364
|
+
state.runs = result.items || []; renderRuns(); setI18nText($('run-page'), result.nextCursor ? 'nextPage' : 'end');
|
|
256
365
|
if (!state.selectedRun && state.runs[0]) await loadRunDetail(state.runs[0].runId);
|
|
257
366
|
else renderRunDetail();
|
|
258
367
|
} catch (error) { setStatus(error.message, true); }
|
|
259
368
|
}
|
|
260
369
|
|
|
261
|
-
async function loadEntries() { if (!state.workspace) return; try { const params = new URLSearchParams({ workspace: state.workspace }); if (state.kind !== 'all') params.set('kind', state.kind); if (state.tag) params.set('tag', state.tag); if (state.query) params.set('q', state.query); const result = await api('/api/entries?' + params); state.entries = result.entries; if (state.selected && !state.entries.some((entry) => entry.id === state.selected.id)) state.selected = null; renderEntries(); renderFilters(); if (!state.selected && state.entries[0]) await selectEntry(state.entries[0].id); else renderEditor();
|
|
370
|
+
async function loadEntries() { if (!state.workspace) return; try { const params = new URLSearchParams({ workspace: state.workspace }); if (state.kind !== 'all') params.set('kind', state.kind); if (state.tag) params.set('tag', state.tag); if (state.query) params.set('q', state.query); const result = await api('/api/entries?' + params); state.entries = result.entries; if (state.selected && !state.entries.some((entry) => entry.id === state.selected.id)) state.selected = null; renderEntries(); renderFilters(); if (!state.selected && state.entries[0]) await selectEntry(state.entries[0].id); else renderEditor(); setLocalizedCountStatus('displayedCount', result.entries.length); } catch (error) { setStatus(error.message, true); } }
|
|
262
371
|
async function loadTags() { if (!state.workspace) return; try { const result = await api('/api/tags?workspace=' + encodeURIComponent(state.workspace)); state.tags = result.tags; renderFilters(); } catch (error) { setStatus(error.message, true); } }
|
|
263
|
-
async function loadWorkspaces() { try { const result = await api('/api/workspaces'); const select = $('workspace'); select.replaceChildren(...result.workspaces.map((item) => { const option = document.createElement('option'); option.value = item.workspace; option.textContent = (item.displayName || item.workspace) + ' (' + item.count + ')'; return option; })); if (!state.workspace && result.workspaces[0]) state.workspace = result.workspaces[0].workspace; select.value = state.workspace; if (state.workspace) { await loadTags(); await loadEntries(); await loadRuns(); } else
|
|
372
|
+
async function loadWorkspaces() { try { const result = await api('/api/workspaces'); const select = $('workspace'); select.replaceChildren(...result.workspaces.map((item) => { const option = document.createElement('option'); option.value = item.workspace; option.textContent = (item.displayName || item.workspace) + ' (' + item.count + ')'; return option; })); if (!state.workspace && result.workspaces[0]) state.workspace = result.workspaces[0].workspace; select.value = state.workspace; if (state.workspace) { await loadTags(); await loadEntries(); await loadRuns(); } else setLocalizedStatus('noWorkspace', {}, true); } catch (error) { setStatus(error.message, true); } }
|
|
373
|
+
$('language-toggle').addEventListener('click', () => {
|
|
374
|
+
setLanguageMenuOpen($('language-toggle').getAttribute('aria-expanded') !== 'true');
|
|
375
|
+
});
|
|
376
|
+
$('language-toggle').addEventListener('keydown', (event) => {
|
|
377
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;
|
|
378
|
+
event.preventDefault();
|
|
379
|
+
setLanguageMenuOpen(true);
|
|
380
|
+
});
|
|
381
|
+
$('language-menu').addEventListener('keydown', (event) => {
|
|
382
|
+
const options = [...$('language-menu').querySelectorAll('.language-option')];
|
|
383
|
+
const current = options.indexOf(document.activeElement);
|
|
384
|
+
let next = null;
|
|
385
|
+
if (event.key === 'ArrowDown') next = options[(current + 1) % options.length];
|
|
386
|
+
if (event.key === 'ArrowUp') next = options[(current - 1 + options.length) % options.length];
|
|
387
|
+
if (event.key === 'Home') next = options[0];
|
|
388
|
+
if (event.key === 'End') next = options.at(-1);
|
|
389
|
+
if (event.key === 'Escape') { event.preventDefault(); setLanguageMenuOpen(false, true); return; }
|
|
390
|
+
if (next) { event.preventDefault(); next.focus(); }
|
|
391
|
+
});
|
|
392
|
+
document.addEventListener('click', (event) => { if (!$('language-picker')?.contains(event.target)) setLanguageMenuOpen(false); });
|
|
393
|
+
document.addEventListener('focusin', (event) => { if (!$('language-picker')?.contains(event.target)) setLanguageMenuOpen(false); });
|
|
264
394
|
$('workspace').addEventListener('change', (event) => { state.workspace = event.target.value; state.selected = null; state.selectedRun = null; state.runs = []; state.tag = ''; loadTags().then(loadEntries).then(loadRuns); });
|
|
265
395
|
$('refresh').addEventListener('click', () => loadWorkspaces());
|
|
266
396
|
let searchTimer; $('search').addEventListener('input', (event) => { clearTimeout(searchTimer); state.query = event.target.value.trim(); searchTimer = setTimeout(() => loadEntries(), 180); });
|
|
397
|
+
applyTranslations();
|
|
267
398
|
loadWorkspaces();
|
|
268
399
|
</script>
|
|
269
400
|
</body>
|
package/dist/web/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE7F,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC;IACrC,aAAa,EAAE,kBAAkB;IACjC,YAAY,EAAE,iBAAiB;IAC/B,OAAO,EAAE,WAAW;IACpB,QAAQ,EAAE,YAAY;CACvB,CAAC;KACC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;KAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;KAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;KAC1B,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC;KAC/B,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAEnC,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAmIf,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiQ1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askdkc/kiokuko",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Model-agnostic external memory for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"kiokuko": "dist/bin/kiokuko.js"
|
|
8
8
|
},
|
|
9
9
|
"engines": {
|
|
10
|
-
"node": ">=
|
|
10
|
+
"node": ">=24.0.0"
|
|
11
11
|
},
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "public"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"zod": "^4.4.3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^
|
|
41
|
+
"@types/node": "^24.0.0",
|
|
42
42
|
"tsx": "^4.20.3",
|
|
43
43
|
"typescript": "^5.9.2"
|
|
44
44
|
}
|
package/templates/AGENTS.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- BEGIN KIOKUKO MANAGED BLOCK -->
|
|
2
|
-
<!-- kiokuko-template-version:
|
|
2
|
+
<!-- kiokuko-template-version: 5 -->
|
|
3
3
|
<!-- This section is managed by `kiokuko use`. Edit outside the markers. -->
|
|
4
4
|
|
|
5
5
|
## Kiokuko external memory
|
|
@@ -14,7 +14,7 @@ Use the Kiokuko MCP tools rather than reading or modifying the SQLite file direc
|
|
|
14
14
|
|
|
15
15
|
### Before non-trivial work
|
|
16
16
|
|
|
17
|
-
1. Call `task_prepare` with the actual task, current working directory, and only profile hints supported by the user request or repository evidence.
|
|
17
|
+
1. Call `task_prepare` at most once for the current user request, with the actual task, current working directory, and only profile hints supported by the user request or repository evidence. Reuse its result for the rest of the request; never call it again after `memory_checkpoint`.
|
|
18
18
|
2. Include the complete names and short descriptions of skills and MCP tools available in the current client. Pass an empty catalog only when none are available; omit it when availability is unknown. The catalog is not stored.
|
|
19
19
|
3. Kiokuko may consult `https://github.com/mattpocock/skills` only when the supplied catalog contains zero skills. If any skill is available, or the catalog is unknown, external skill fallback stays disabled.
|
|
20
20
|
4. If the intake needs an answer, call `task_answer` with the same capability catalog only when current evidence supports the answer; otherwise ask the user the returned question.
|
|
@@ -23,9 +23,11 @@ Use the Kiokuko MCP tools rather than reading or modifying the SQLite file direc
|
|
|
23
23
|
|
|
24
24
|
### After substantial work
|
|
25
25
|
|
|
26
|
-
1. Call `memory_checkpoint` only for concise, durable, verified facts, decisions, lessons, preferences, or references that will help future work.
|
|
27
|
-
2.
|
|
28
|
-
3.
|
|
26
|
+
1. Call `memory_checkpoint` at most once for the current user request, only for concise, durable, verified facts, decisions, lessons, preferences, or references that will help future work.
|
|
27
|
+
2. Treat a completed `memory_checkpoint` as terminal for tool use: do not call it or any other tool again; immediately return the final response.
|
|
28
|
+
3. Do not retry an unchanged tool call after it fails or returns no new information. Summarize the blocker or current result and stop tool use.
|
|
29
|
+
4. Keep repository knowledge in project scope. Use global scope only for knowledge that truly applies across projects.
|
|
30
|
+
5. Checkpoints remain untrusted candidates until explicitly reviewed; never auto-promote them to verified.
|
|
29
31
|
|
|
30
32
|
If the MCP tools are unavailable, report the failure briefly and continue from repository evidence. Never store passwords, API keys, access tokens, private keys, session cookies, auth headers, provider credentials, client secrets, private user data, full transcripts, or capability catalogs.
|
|
31
33
|
|