codexmate 0.0.33 → 0.0.36
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/cli/agents-files.js +6 -0
- package/cli/archive-helpers.js +11 -4
- package/cli/local-bridge.js +9 -4
- package/cli/openai-bridge.js +1 -1
- package/cli/update.js +11 -2
- package/cli.js +133 -64
- package/lib/cli-webhook.js +29 -1
- package/package.json +2 -1
- package/web-ui/app.js +37 -2
- package/web-ui/index.html +2 -1
- package/web-ui/logic.claude.mjs +4 -0
- package/web-ui/logic.sessions.mjs +6 -5
- package/web-ui/modules/app.computed.dashboard.mjs +4 -0
- package/web-ui/modules/app.computed.session.mjs +147 -6
- package/web-ui/modules/app.methods.claude-config.mjs +41 -0
- package/web-ui/modules/app.methods.codex-config.mjs +11 -3
- package/web-ui/modules/app.methods.navigation.mjs +32 -2
- package/web-ui/modules/app.methods.session-browser.mjs +12 -6
- package/web-ui/modules/app.methods.session-trash.mjs +30 -0
- package/web-ui/modules/app.methods.startup-claude.mjs +9 -0
- package/web-ui/modules/app.methods.webhook.mjs +8 -0
- package/web-ui/modules/i18n.dict.mjs +8 -0
- package/web-ui/modules/sessions-filters-url.mjs +65 -12
- package/web-ui/modules/skills.methods.mjs +31 -0
- package/web-ui/partials/index/layout-header.html +17 -12
- package/web-ui/partials/index/modal-webhook.html +42 -0
- package/web-ui/partials/index/modals-basic.html +50 -0
- package/web-ui/partials/index/panel-config-claude.html +13 -22
- package/web-ui/partials/index/panel-config-codex.html +8 -22
- package/web-ui/partials/index/panel-market.html +76 -149
- package/web-ui/partials/index/panel-sessions.html +2 -2
- package/web-ui/partials/index/panel-settings.html +119 -149
- package/web-ui/partials/index/panel-usage.html +115 -68
- package/web-ui/res/vue.runtime.global.prod.js +7 -0
- package/web-ui/res/web-ui-render.precompiled.js +7274 -0
- package/web-ui/session-helpers.mjs +15 -4
- package/web-ui/source-bundle.cjs +73 -1
- package/web-ui/styles/base-theme.css +10 -0
- package/web-ui/styles/bridge-pool.css +69 -0
- package/web-ui/styles/layout-shell.css +66 -27
- package/web-ui/styles/navigation-panels.css +8 -0
- package/web-ui/styles/responsive.css +50 -9
- package/web-ui/styles/sessions-usage.css +336 -319
- package/web-ui/styles/settings-panel.css +300 -234
- package/web-ui/styles/skills-market.css +294 -0
- package/web-ui/styles/titles-cards.css +14 -0
- package/web-ui/styles/webhook.css +38 -4
|
@@ -4,172 +4,99 @@
|
|
|
4
4
|
id="panel-market"
|
|
5
5
|
role="tabpanel"
|
|
6
6
|
aria-labelledby="tab-market">
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
<!-- Minimalist header with target switch -->
|
|
8
|
+
<div class="skills-minimal-header">
|
|
9
|
+
<div class="skills-header-left">
|
|
10
|
+
<span class="skills-header-title">{{ t('market.title') }}</span>
|
|
11
|
+
<div class="skills-target-switch" role="group" :aria-label="t('market.target.aria')">
|
|
12
|
+
<button
|
|
13
|
+
type="button"
|
|
14
|
+
:class="['skills-target-chip', { active: skillsTargetApp === 'codex' }]"
|
|
15
|
+
:aria-pressed="skillsTargetApp === 'codex'"
|
|
16
|
+
:disabled="loading || !!initError || skillsMarketBusy"
|
|
17
|
+
@click="setSkillsTargetApp('codex', { silent: false })">
|
|
18
|
+
Codex
|
|
19
19
|
</button>
|
|
20
|
-
<button
|
|
21
|
-
|
|
20
|
+
<button
|
|
21
|
+
type="button"
|
|
22
|
+
:class="['skills-target-chip', { active: skillsTargetApp === 'claude' }]"
|
|
23
|
+
:aria-pressed="skillsTargetApp === 'claude'"
|
|
24
|
+
:disabled="loading || !!initError || skillsMarketBusy"
|
|
25
|
+
@click="setSkillsTargetApp('claude', { silent: false })">
|
|
26
|
+
Claude Code
|
|
22
27
|
</button>
|
|
23
28
|
</div>
|
|
24
29
|
</div>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
type="button"
|
|
29
|
-
:class="['market-target-chip', { active: skillsTargetApp === 'codex' }]"
|
|
30
|
-
:aria-pressed="skillsTargetApp === 'codex'"
|
|
31
|
-
:disabled="loading || !!initError || skillsMarketBusy"
|
|
32
|
-
@click="setSkillsTargetApp('codex', { silent: false })">
|
|
33
|
-
Codex
|
|
30
|
+
<div class="skills-header-actions">
|
|
31
|
+
<button type="button" class="btn-icon" @click="openSkillsMenu" :aria-label="t('common.menu')" :title="t('common.menu')">
|
|
32
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>
|
|
34
33
|
</button>
|
|
35
|
-
<button
|
|
36
|
-
type="button"
|
|
37
|
-
:class="['market-target-chip', { active: skillsTargetApp === 'claude' }]"
|
|
38
|
-
:aria-pressed="skillsTargetApp === 'claude'"
|
|
39
|
-
:disabled="loading || !!initError || skillsMarketBusy"
|
|
40
|
-
@click="setSkillsTargetApp('claude', { silent: false })">
|
|
41
|
-
Claude Code
|
|
42
|
-
</button>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div class="skills-root-box market-root-box">{{ skillsRootPath || skillsDefaultRootPath }}</div>
|
|
46
|
-
|
|
47
|
-
<div class="skills-summary-strip market-summary-strip">
|
|
48
|
-
<div class="skills-summary-item">
|
|
49
|
-
<span class="skills-summary-label">{{ t('market.summary.target') }}</span>
|
|
50
|
-
<strong class="skills-summary-value">{{ skillsTargetLabel }}</strong>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="skills-summary-item">
|
|
53
|
-
<span class="skills-summary-label">{{ t('market.summary.total') }}</span>
|
|
54
|
-
<strong class="skills-summary-value">{{ skillsList.length }}</strong>
|
|
55
|
-
</div>
|
|
56
|
-
<div class="skills-summary-item">
|
|
57
|
-
<span class="skills-summary-label">{{ t('market.summary.configured') }}</span>
|
|
58
|
-
<strong class="skills-summary-value">{{ skillsConfiguredCount }}</strong>
|
|
59
|
-
</div>
|
|
60
|
-
<div class="skills-summary-item">
|
|
61
|
-
<span class="skills-summary-label">{{ t('market.summary.missing') }}</span>
|
|
62
|
-
<strong class="skills-summary-value">{{ skillsMissingSkillFileCount }}</strong>
|
|
63
|
-
</div>
|
|
64
|
-
<div class="skills-summary-item">
|
|
65
|
-
<span class="skills-summary-label">{{ t('market.summary.importable') }}</span>
|
|
66
|
-
<strong class="skills-summary-value">{{ skillsImportList.length }}</strong>
|
|
67
|
-
</div>
|
|
68
|
-
<div class="skills-summary-item">
|
|
69
|
-
<span class="skills-summary-label">{{ t('market.summary.importableDirect') }}</span>
|
|
70
|
-
<strong class="skills-summary-value">{{ skillsImportConfiguredCount }}</strong>
|
|
71
|
-
</div>
|
|
72
34
|
</div>
|
|
73
35
|
</div>
|
|
74
36
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
</
|
|
86
|
-
<div v-if="skillsLoading && !skillsMarketLocalLoadedOnce" class="skills-empty-state">{{ t('market.local.loading') }}</div>
|
|
87
|
-
<div v-else-if="skillsList.length === 0" class="skills-empty-state">{{ t('market.local.empty') }}</div>
|
|
88
|
-
<div v-else class="market-preview-list">
|
|
89
|
-
<div v-for="skill in skillsMarketInstalledPreview" :key="'market-local-' + skill.name" class="market-preview-item">
|
|
90
|
-
<div class="market-preview-main">
|
|
91
|
-
<div class="market-preview-title">{{ skill.displayName || skill.name }}</div>
|
|
92
|
-
<div class="market-preview-meta">{{ skill.description || skill.path }}</div>
|
|
93
|
-
</div>
|
|
94
|
-
<span :class="['pill', skill.hasSkillFile ? 'configured' : 'empty']">
|
|
95
|
-
{{ skill.hasSkillFile ? t('market.pill.verified') : t('market.pill.missingSkill') }}
|
|
96
|
-
</span>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
37
|
+
<!-- Installed skills panel -->
|
|
38
|
+
<div class="skills-flow-panel">
|
|
39
|
+
<div class="skills-flow-header">
|
|
40
|
+
<div class="skills-flow-title-wrap">
|
|
41
|
+
<span class="skills-flow-title">{{ t('market.installed.title') }}</span>
|
|
42
|
+
<span class="skills-flow-count">{{ skillsList.length }}</span>
|
|
43
|
+
</div>
|
|
44
|
+
<button type="button" class="btn-mini" @click="refreshSkillsList({ silent: false })" :disabled="loading || !!initError || skillsMarketBusy">
|
|
45
|
+
<svg v-if="!skillsLoading" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="14" height="14"><path d="M17 1l4 4-4 4"/><path d="M3 11V9a4 4 0 014-4h14"/><path d="M3 19l-4-4 4-4"/><path d="M17 9v2a4 4 0 01-4 4H3"/></svg>
|
|
46
|
+
<svg v-else viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="14" height="14" class="spin"><path d="M10 2v4m0 8v4M2 10h4m8 0h4m-3.5-6.5l2.5 2.5M4 4l2.5 2.5M16 16l-2.5-2.5M4 16l2.5-2.5"/></svg>
|
|
47
|
+
</button>
|
|
99
48
|
</div>
|
|
100
|
-
|
|
101
|
-
<div class="skills-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
<button type="button" class="btn-mini" @click="scanImportableSkills({ silent: false })" :disabled="loading || !!initError || skillsMarketBusy">
|
|
108
|
-
{{ skillsScanningImports ? t('market.import.scanning') : t('market.import.scan') }}
|
|
109
|
-
</button>
|
|
110
|
-
</div>
|
|
111
|
-
<div v-if="skillsScanningImports && !skillsMarketImportLoadedOnce" class="skills-empty-state">{{ t('market.import.loading') }}</div>
|
|
112
|
-
<div v-else-if="skillsImportList.length === 0" class="skills-empty-state">{{ t('market.import.empty') }}</div>
|
|
113
|
-
<div v-else class="market-preview-list">
|
|
114
|
-
<div v-for="skill in skillsMarketImportPreview" :key="'market-import-' + buildSkillImportKey(skill)" class="market-preview-item">
|
|
115
|
-
<div class="market-preview-main">
|
|
116
|
-
<div class="market-preview-title">{{ skill.displayName || skill.name }}</div>
|
|
117
|
-
<div class="market-preview-meta">{{ skill.sourceLabel }} · {{ skill.sourcePath }}</div>
|
|
118
|
-
</div>
|
|
119
|
-
<span :class="['pill', skill.hasSkillFile ? 'configured' : 'empty']">
|
|
120
|
-
{{ skill.hasSkillFile ? t('market.pill.importableDirect') : t('market.pill.importMissing') }}
|
|
121
|
-
</span>
|
|
49
|
+
<div v-if="skillsLoading && !skillsMarketLocalLoadedOnce" class="skills-flow-loading">{{ t('market.local.loading') }}</div>
|
|
50
|
+
<div v-else-if="skillsList.length === 0" class="skills-flow-empty">{{ t('market.local.empty') }}</div>
|
|
51
|
+
<div v-else class="skills-flow-list">
|
|
52
|
+
<div v-for="skill in skillsList" :key="'skill-' + skill.name" class="skills-flow-item" :class="{ 'has-issue': !skill.hasSkillFile }">
|
|
53
|
+
<div class="skills-flow-main">
|
|
54
|
+
<span class="skills-flow-name">{{ skill.displayName || skill.name }}</span>
|
|
55
|
+
<span class="skills-flow-path">{{ skill.path }}</span>
|
|
122
56
|
</div>
|
|
57
|
+
<span :class="['skills-flow-status', skill.hasSkillFile ? 'success' : 'warning']">
|
|
58
|
+
{{ skill.hasSkillFile ? t('market.pill.verified') : t('market.pill.missingSkill') }}
|
|
59
|
+
</span>
|
|
123
60
|
</div>
|
|
124
61
|
</div>
|
|
62
|
+
</div>
|
|
125
63
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
</
|
|
132
|
-
</div>
|
|
133
|
-
<
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
64
|
+
<!-- Importable skills panel -->
|
|
65
|
+
<div class="skills-flow-panel">
|
|
66
|
+
<div class="skills-flow-header">
|
|
67
|
+
<div class="skills-flow-title-wrap">
|
|
68
|
+
<span class="skills-flow-title">{{ t('market.import.title') }}</span>
|
|
69
|
+
<span class="skills-flow-count">{{ skillsImportList.length }}</span>
|
|
70
|
+
</div>
|
|
71
|
+
<button type="button" class="btn-mini" @click="scanImportableSkills({ silent: false })" :disabled="loading || !!initError || skillsMarketBusy">
|
|
72
|
+
<svg v-if="!skillsScanningImports" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="14" height="14"><path d="M17 1l4 4-4 4"/><path d="M3 11V9a4 4 0 014-4h14"/><path d="M3 19l-4-4 4-4"/><path d="M17 9v2a4 4 0 01-4 4H3"/></svg>
|
|
73
|
+
<svg v-else viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="14" height="14" class="spin"><path d="M10 2v4m0 8v4M2 10h4m8 0h4m-3.5-6.5l2.5 2.5M4 4l2.5 2.5M16 16l-2.5-2.5M4 16l2.5-2.5"/></svg>
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
<div v-if="skillsScanningImports && !skillsMarketImportLoadedOnce" class="skills-flow-loading">{{ t('market.import.loading') }}</div>
|
|
77
|
+
<div v-else-if="skillsImportList.length === 0" class="skills-flow-empty">{{ t('market.import.empty') }}</div>
|
|
78
|
+
<div v-else>
|
|
79
|
+
<!-- Quick actions -->
|
|
80
|
+
<div class="skills-flow-actions">
|
|
81
|
+
<button type="button" class="skills-action-btn" @click="openSkillsManager" :disabled="loading || !!initError || skillsMarketBusy">
|
|
82
|
+
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="16" height="16"><rect x="3" y="3" width="14" height="14" rx="3"/><path d="M7 7h6M7 10h4"/></svg>
|
|
83
|
+
{{ t('market.action.manage.title') }}
|
|
141
84
|
</button>
|
|
142
|
-
<button type="button" class="
|
|
143
|
-
<
|
|
144
|
-
|
|
85
|
+
<button type="button" class="skills-action-btn" @click="triggerSkillsZipImport" :disabled="loading || !!initError || skillsMarketBusy">
|
|
86
|
+
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="16" height="16"><path d="M4 14l3-3 3 3"/><path d="M7 4v7"/><rect x="12" y="4" width="5" height="12" rx="1"/></svg>
|
|
87
|
+
{{ t('market.action.zipImport.title') }}
|
|
145
88
|
</button>
|
|
146
89
|
</div>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
<div class="market-preview-list">
|
|
156
|
-
<div class="market-preview-item">
|
|
157
|
-
<div class="market-preview-main">
|
|
158
|
-
<div class="market-preview-title">{{ t('market.help.target.title') }}</div>
|
|
159
|
-
<div class="market-preview-meta">{{ t('market.help.target.copy', { target: skillsTargetLabel }) }}</div>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
<div class="market-preview-item">
|
|
163
|
-
<div class="market-preview-main">
|
|
164
|
-
<div class="market-preview-title">{{ t('market.help.crossImport.title') }}</div>
|
|
165
|
-
<div class="market-preview-meta">{{ t('market.help.crossImport.copy') }}</div>
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
<div class="market-preview-item">
|
|
169
|
-
<div class="market-preview-main">
|
|
170
|
-
<div class="market-preview-title">{{ t('market.help.zipImport.title') }}</div>
|
|
171
|
-
<div class="market-preview-meta">{{ t('market.help.zipImport.copy') }}</div>
|
|
90
|
+
<!-- Import list -->
|
|
91
|
+
<div class="skills-flow-list">
|
|
92
|
+
<div v-for="skill in skillsImportList" :key="'import-' + buildSkillImportKey(skill)" class="skills-flow-item">
|
|
93
|
+
<div class="skills-flow-main">
|
|
94
|
+
<span class="skills-flow-name">{{ skill.displayName || skill.name }}</span>
|
|
95
|
+
<span class="skills-flow-meta">{{ skill.sourceLabel }}</span>
|
|
172
96
|
</div>
|
|
97
|
+
<button type="button" class="skills-flow-add" @click="importSingleSkill(skill)" :disabled="loading || !!initError || skillsMarketBusy">
|
|
98
|
+
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.8" width="16" height="16"><path d="M10 4v6m3-3l-3 3-3-3"/></svg>
|
|
99
|
+
</button>
|
|
173
100
|
</div>
|
|
174
101
|
</div>
|
|
175
102
|
</div>
|
|
@@ -193,7 +193,7 @@
|
|
|
193
193
|
</div>
|
|
194
194
|
<div class="session-item-meta">
|
|
195
195
|
<span class="session-source" :data-source="session.source">{{ session.sourceLabel }}</span>
|
|
196
|
-
<span class="session-item-time">{{ session.updatedAt || t('sessions.unknownTime') }}</span>
|
|
196
|
+
<span class="session-item-time">{{ session.updatedAtLabel || session.updatedAt || t('sessions.unknownTime') }}</span>
|
|
197
197
|
<span v-if="getSessionHotLabel(session)" class="session-item-hot">{{ getSessionHotLabel(session) }}</span>
|
|
198
198
|
<span v-if="session.cwd" class="session-item-cwd session-item-sub">{{ session.cwd }}</span>
|
|
199
199
|
<div v-if="session.match && session.match.snippets && session.match.snippets.length" class="session-match-snippets">
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
<div class="session-preview-title">{{ activeSession.title || activeSession.sessionId }}</div>
|
|
213
213
|
<div class="session-preview-meta">
|
|
214
214
|
<span class="session-preview-meta-item session-source" :data-source="activeSession.source">{{ activeSession.sourceLabel }}</span>
|
|
215
|
-
<span class="session-preview-meta-item">{{ activeSession.updatedAt || t('sessions.unknownTime') }}</span>
|
|
215
|
+
<span class="session-preview-meta-item">{{ activeSession.updatedAtLabel || activeSession.updatedAt || t('sessions.unknownTime') }}</span>
|
|
216
216
|
</div>
|
|
217
217
|
<div class="session-preview-meta" v-if="activeSession.cwd">
|
|
218
218
|
<span class="session-preview-meta-item">{{ activeSession.cwd }}</span>
|