dsh-shortcut-extensions 1.0.0 → 1.1.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 +5 -0
- package/README.zh.md +5 -0
- package/client.js +261 -108
- package/icon.svg +8 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
A [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) plugin that adds a keyboard-driven quick-switching layer to the DSH web/desktop UI: a model palette, a session palette with prompt preview, session cycling, find-next-answered, composer focus, and configurable permission cycling — all manageable from a sidebar control panel.
|
|
8
8
|
|
|
9
9
|
中文说明见 [README.zh.md](README.zh.md)。
|
|
10
|
+
- **Header chips** — the current workspace name and git branch sit right beside the session title (`conversation.session.header.actions`); the branch is re-read whenever you enter a session.
|
|
10
11
|
|
|
11
12
|
## Features
|
|
12
13
|
|
|
@@ -62,6 +63,10 @@ dsh-shortcut-extensions/
|
|
|
62
63
|
└── icon.svg
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
## Icons / 图标
|
|
67
|
+
|
|
68
|
+
- Icons: [Lucide](https://lucide.dev) — `keyboard`, `cpu`, `messages-square`, `arrow-left`, `arrow-right`, `search-check`, `text-cursor-input`, `shield`, `shield-half`, `panel-left`, `message-circle`, `layout-grid`, `message-square-plus` (ISC License).
|
|
69
|
+
|
|
65
70
|
## License
|
|
66
71
|
|
|
67
72
|
[MIT](LICENSE)
|
package/README.zh.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
一个 [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) 插件,为 DSH 网页/桌面界面增加一层**键盘驱动的快速切换**:模型面板、带提问预览的会话面板、会话循环、查找下一个已回答会话、聚焦输入框、可配置的权限循环——全部可以在侧栏控制面板里管理。
|
|
8
8
|
|
|
9
9
|
English documentation: [README.md](README.md)。
|
|
10
|
+
- **页头标签** — 在会话标题右侧显示当前工作区名与 git 分支(`conversation.session.header.actions`),每次进入会话都会重新读取分支。
|
|
10
11
|
|
|
11
12
|
## 功能
|
|
12
13
|
|
|
@@ -62,6 +63,10 @@ dsh-shortcut-extensions/
|
|
|
62
63
|
└── icon.svg
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
## 图标 / Icons
|
|
67
|
+
|
|
68
|
+
- 图标:[Lucide](https://lucide.dev)(`keyboard`、`cpu`、`messages-square`、`arrow-left`、`arrow-right`、`search-check`、`text-cursor-input`、`shield`、`shield-half`、`panel-left`、`message-circle`、`layout-grid`、`message-square-plus`,ISC 许可证)。
|
|
69
|
+
|
|
65
70
|
## 许可证
|
|
66
71
|
|
|
67
72
|
[MIT](LICENSE)
|
package/client.js
CHANGED
|
@@ -375,8 +375,8 @@ window.__ModuleLoader__.load({
|
|
|
375
375
|
labelKey: 'action.newSession',
|
|
376
376
|
impl: 'uiWorkspace.startSession()',
|
|
377
377
|
run: (d) => { try { d.ctx.uiWorkspace.startSession(); } catch (error) { console.error('[shortcut-ext] startSession failed', error); } }
|
|
378
|
-
}
|
|
379
|
-
|
|
378
|
+
},
|
|
379
|
+
];
|
|
380
380
|
|
|
381
381
|
const ACTION_BY_ID = new Map(ACTIONS.map((action) => [action.id, action]));
|
|
382
382
|
|
|
@@ -497,7 +497,7 @@ window.__ModuleLoader__.load({
|
|
|
497
497
|
},
|
|
498
498
|
{}
|
|
499
499
|
]
|
|
500
|
-
}
|
|
500
|
+
},
|
|
501
501
|
];
|
|
502
502
|
|
|
503
503
|
const COMMAND_IDS = COMMANDS.map((command) => command.id);
|
|
@@ -507,12 +507,13 @@ window.__ModuleLoader__.load({
|
|
|
507
507
|
/* ------------------------------------------------------------------ */
|
|
508
508
|
|
|
509
509
|
const CSS = [
|
|
510
|
-
/* Palettes:
|
|
510
|
+
/* Palettes: menu-toned surface over an opaque base (no see-through) */
|
|
511
511
|
'.dqs-backdrop{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;',
|
|
512
512
|
'background:rgba(0,0,0,.32);}',
|
|
513
513
|
'.dqs-palette{width:min(720px,calc(100vw - 48px));max-height:min(70vh,660px);display:flex;flex-direction:column;',
|
|
514
|
-
'overflow:hidden;background:var(--dsw-
|
|
515
|
-
'
|
|
514
|
+
'overflow:hidden;background-color:var(--dsw-alias-bg-layer-1,var(--dsw-alias-bg-overlay));',
|
|
515
|
+
'background-image:linear-gradient(var(--dsw-specific-menu,var(--dsw-alias-bg-overlay)),',
|
|
516
|
+
'var(--dsw-specific-menu,var(--dsw-alias-bg-overlay)));',
|
|
516
517
|
'border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-lg,14px);',
|
|
517
518
|
'box-shadow:var(--dsw-elevation-prominent,0 12px 32px rgba(0,0,0,.28));color:var(--dsw-alias-label-primary);}',
|
|
518
519
|
'.dqs-paletteHead{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px 18px 10px;}',
|
|
@@ -522,18 +523,25 @@ window.__ModuleLoader__.load({
|
|
|
522
523
|
'.dqs-closeBtn:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2));',
|
|
523
524
|
'color:var(--dsw-alias-label-primary);}',
|
|
524
525
|
'.dqs-input{width:100%;box-sizing:border-box;height:40px;padding:0 12px 0 34px;',
|
|
525
|
-
'border:
|
|
526
|
-
'color:var(--dsw-alias-label-primary);font-size:13px;outline:none;}',
|
|
526
|
+
'border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2);',
|
|
527
|
+
'color:var(--dsw-alias-label-primary);font-size:13px;outline:none;transition:border-color .12s;}',
|
|
527
528
|
'.dqs-input::placeholder{color:var(--dsw-alias-label-secondary);opacity:.8;}',
|
|
528
|
-
'.dqs-input:focus{
|
|
529
|
+
'.dqs-input:hover:not(:focus){border-color:var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));}',
|
|
530
|
+
'.dqs-input:focus{border-color:var(--dsw-alias-state-business-primary);}',
|
|
529
531
|
'.dqs-searchWrap{position:relative;margin:0 14px 10px;}',
|
|
530
532
|
'.dqs-searchIcon{position:absolute;left:11px;top:50%;transform:translateY(-50%);',
|
|
531
533
|
'color:var(--dsw-alias-label-secondary);display:flex;pointer-events:none;}',
|
|
532
|
-
'.dqs-list{height:
|
|
533
|
-
'.dqs-
|
|
534
|
-
'.dqs-
|
|
534
|
+
'.dqs-list{height:360px;overflow-y:auto;padding:2px 8px 6px;}',
|
|
535
|
+
'.dqs-list::-webkit-scrollbar{width:8px;height:8px;}',
|
|
536
|
+
'.dqs-list::-webkit-scrollbar-track{background:transparent;}',
|
|
537
|
+
'.dqs-list::-webkit-scrollbar-thumb{background:var(--dsw-alias-scrollbar-bg-l2,var(--dsw-alias-border-l2));',
|
|
538
|
+
'border-radius:999px;}',
|
|
539
|
+
'.dqs-list::-webkit-scrollbar-thumb:hover{background:var(--dsw-alias-scrollbar-hover-l2,var(--dsw-alias-border-l1));}',
|
|
540
|
+
'.dqs-columns{display:flex;height:360px;min-height:0;}',
|
|
541
|
+
'.dqs-columns .dqs-list{flex:1 1 auto;height:100%;min-width:0;border-right:none;}',
|
|
535
542
|
'.dqs-paletteWide{width:min(880px,calc(100vw - 48px));}',
|
|
536
|
-
'.dqs-row{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;cursor:pointer;
|
|
543
|
+
'.dqs-row{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;cursor:pointer;',
|
|
544
|
+
'font-size:14px;min-height:36px;box-sizing:border-box;}',
|
|
537
545
|
'.dqs-row[data-active="true"]{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2));}',
|
|
538
546
|
'.dqs-rowName{flex:0 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}',
|
|
539
547
|
'.dqs-rowProvider{flex:1 1 auto;min-width:0;color:var(--dsw-alias-label-secondary);font-size:12px;',
|
|
@@ -561,20 +569,30 @@ window.__ModuleLoader__.load({
|
|
|
561
569
|
'.dqs-pinBtn[data-pinned="true"]{color:var(--dsw-alias-brand-primary);}',
|
|
562
570
|
'.dqs-status{padding:10px 16px;font-size:12px;color:var(--dsw-alias-label-secondary);}',
|
|
563
571
|
'.dqs-statusError{color:var(--dsw-alias-state-error-primary);}',
|
|
564
|
-
'.dqs-footer{padding:
|
|
565
|
-
'border-top:.5px solid var(--dsw-alias-border-l1);display:flex;gap:
|
|
566
|
-
'.dqs-
|
|
567
|
-
'
|
|
572
|
+
'.dqs-footer{padding:12px 18px 13px;font-size:12px;color:var(--dsw-alias-label-secondary);',
|
|
573
|
+
'border-top:.5px solid var(--dsw-alias-border-l1);display:flex;align-items:center;gap:8px 22px;flex-wrap:wrap;}',
|
|
574
|
+
'.dqs-hintItem{display:inline-flex;align-items:center;gap:7px;white-space:nowrap;}',
|
|
575
|
+
'.dqs-kbd{border:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));',
|
|
576
|
+
'background:var(--dsw-alias-bg-layer-1);border-radius:5px;',
|
|
577
|
+
'min-width:22px;height:20px;padding:0 7px;box-sizing:border-box;text-align:center;font-size:11px;',
|
|
578
|
+
'color:var(--dsw-alias-label-secondary);display:inline-flex;align-items:center;justify-content:center;}',
|
|
568
579
|
'.dqs-rowDot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-idle-primary);opacity:.45;}',
|
|
569
580
|
'.dqs-rowDot[data-running="true"]{background:var(--dsw-alias-state-success-primary);opacity:1;}',
|
|
570
581
|
'.dqs-rowPin{flex:none;color:var(--dsw-alias-brand-primary);display:flex;}',
|
|
582
|
+
'.dqs-hdrChip{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 8px;',
|
|
583
|
+
'border-radius:5px;font-size:11px;line-height:1;color:var(--dsw-alias-label-secondary);',
|
|
584
|
+
'background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l1);',
|
|
585
|
+
'max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:6px;}',
|
|
586
|
+
'.dqs-hdrChip:last-child{margin-right:0;}',
|
|
587
|
+
'.dqs-hdrChipLabel{overflow:hidden;text-overflow:ellipsis;}',
|
|
588
|
+
'.dqs-hdrChipIcon{display:flex;flex:none;}',
|
|
571
589
|
'.dqs-badge{flex:none;font-size:11px;color:var(--dsw-alias-state-warn-primary);border:1px solid var(--dsw-alias-border-l1);border-radius:999px;padding:0 8px;line-height:16px;}',
|
|
572
590
|
/* Panel (mirrors the host Plugins page: centered 960px column) */
|
|
573
591
|
'.dqs-page{box-sizing:border-box;height:100%;color:var(--dsw-alias-label-primary);display:flex;',
|
|
574
592
|
'flex-direction:column;align-items:center;gap:26px;padding:0 clamp(24px,4vw,48px) 48px;overflow:auto;}',
|
|
575
593
|
'.dqs-page>*{width:100%;max-width:960px;}',
|
|
576
594
|
'.dqs-pageHead{padding-top:36px;margin-bottom:-6px;}',
|
|
577
|
-
'.dqs-pageTitle{font-size:
|
|
595
|
+
'.dqs-pageTitle{font-size:20px;font-weight:500;line-height:28px;margin:0 0 6px;}',
|
|
578
596
|
'.dqs-pageSub{font-size:13px;color:var(--dsw-alias-label-secondary);margin:0;}',
|
|
579
597
|
'.dqs-toolbar{display:flex;align-items:center;gap:16px;flex-wrap:wrap;}',
|
|
580
598
|
'.dqs-tabs{display:flex;gap:2px;padding:3px;border-radius:9px;background:var(--dsw-alias-bg-layer-2);}',
|
|
@@ -589,9 +607,10 @@ window.__ModuleLoader__.load({
|
|
|
589
607
|
'.dqs-linkBtn:hover{text-decoration:underline;}',
|
|
590
608
|
'.dqs-search{width:220px;height:32px;padding:0 12px;box-sizing:border-box;border-radius:8px;',
|
|
591
609
|
'border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);',
|
|
592
|
-
'color:var(--dsw-alias-label-primary);font-size:13px;outline:none;}',
|
|
610
|
+
'color:var(--dsw-alias-label-primary);font-size:13px;outline:none;transition:border-color .12s;}',
|
|
593
611
|
'.dqs-search::placeholder{color:var(--dsw-alias-label-secondary);opacity:.7;}',
|
|
594
|
-
'.dqs-search:focus{border-color:var(--dsw-alias-
|
|
612
|
+
'.dqs-search:hover:not(:focus){border-color:var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));}',
|
|
613
|
+
'.dqs-search:focus{border-color:var(--dsw-alias-state-business-primary);}',
|
|
595
614
|
'.dqs-rows{display:flex;flex-direction:column;}',
|
|
596
615
|
'.dqs-cmdRow{display:flex;align-items:center;gap:16px;padding:14px 2px;',
|
|
597
616
|
'border-bottom:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));transition:opacity .15s;}',
|
|
@@ -599,13 +618,13 @@ window.__ModuleLoader__.load({
|
|
|
599
618
|
'.dqs-tile{flex:none;width:48px;height:48px;border-radius:12px;display:flex;align-items:center;justify-content:center;',
|
|
600
619
|
'background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-brand-primary);border:1px solid var(--dsw-alias-border-l1);}',
|
|
601
620
|
'.dqs-cmdInfo{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:3px;}',
|
|
602
|
-
'.dqs-cmdName{font-size:
|
|
603
|
-
'.dqs-cmdImpl{font-size:
|
|
621
|
+
'.dqs-cmdName{font-size:14px;font-weight:400;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}',
|
|
622
|
+
'.dqs-cmdImpl{font-size:11px;color:var(--dsw-alias-label-secondary);',
|
|
604
623
|
'font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}',
|
|
605
624
|
'.dqs-cmdRight{flex:none;display:flex;align-items:center;gap:14px;}',
|
|
606
625
|
'.dqs-cmdKeys{display:flex;align-items:center;gap:3px;}',
|
|
607
626
|
'.dqs-keycap{min-width:20px;height:20px;padding:0 5px;box-sizing:border-box;display:inline-flex;align-items:center;',
|
|
608
|
-
'justify-content:center;border
|
|
627
|
+
'justify-content:center;border:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));border-radius:5px;',
|
|
609
628
|
'font-size:11px;line-height:1;color:var(--dsw-alias-label-secondary);',
|
|
610
629
|
'background:var(--dsw-alias-bg-layer-2);white-space:nowrap;}',
|
|
611
630
|
'.dqs-keycapNone{border:none;background:none;font-size:11px;color:var(--dsw-alias-label-secondary);opacity:.7;}',
|
|
@@ -664,7 +683,7 @@ window.__ModuleLoader__.load({
|
|
|
664
683
|
'.dqs-permCard{border:1px solid var(--dsw-alias-border-l1);border-radius:12px;',
|
|
665
684
|
'background:var(--dsw-alias-bg-layer-1);padding:16px 18px;}',
|
|
666
685
|
'.dqs-sectionHead{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:10px;}',
|
|
667
|
-
'.dqs-sectionTitle{font-size:
|
|
686
|
+
'.dqs-sectionTitle{font-size:14px;font-weight:500;line-height:20px;}',
|
|
668
687
|
'.dqs-chips{display:flex;gap:8px;flex-wrap:wrap;}',
|
|
669
688
|
'.dqs-permChip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));',
|
|
670
689
|
'border-radius:999px;padding:5px 14px;font-size:12px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-secondary);}',
|
|
@@ -679,7 +698,17 @@ window.__ModuleLoader__.load({
|
|
|
679
698
|
'.dqs-expand{padding:2px 2px 18px 64px;}',
|
|
680
699
|
'.dqs-sysRow{display:flex;align-items:center;gap:12px;padding:12px 2px;',
|
|
681
700
|
'border-bottom:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));}',
|
|
682
|
-
'.dqs-sysLabel{flex:1 1 auto;min-width:0;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}',
|
|
701
|
+
'.dqs-sysLabel{flex:1 1 auto;min-width:0;font-size:14px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}',
|
|
702
|
+
'.dqs-tip{position:relative;}',
|
|
703
|
+
'.dqs-tip:hover::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;',
|
|
704
|
+
'transform:translateX(-50%);background:var(--dsw-alias-bg-overlay,var(--dsw-alias-bg-layer-1));',
|
|
705
|
+
'border:.5px solid var(--dsw-alias-border-l1);border-radius:6px;padding:3px 8px;font-size:11px;',
|
|
706
|
+
'line-height:16px;color:var(--dsw-alias-label-primary);white-space:nowrap;z-index:20;',
|
|
707
|
+
'box-shadow:var(--dsw-elevation-prominent,0 6px 16px rgba(0,0,0,.18));pointer-events:none;}',
|
|
708
|
+
'.dqs-iconBtn{flex:none;border:none;background:none;cursor:pointer;display:flex;padding:4px;',
|
|
709
|
+
'border-radius:6px;color:var(--dsw-alias-label-secondary);}',
|
|
710
|
+
'.dqs-iconBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2));}',
|
|
711
|
+
'.dqs-iconBtn[data-hidden="true"]{visibility:hidden;pointer-events:none;}',
|
|
683
712
|
'.dqs-sysFixed{flex:none;font-size:11px;color:var(--dsw-alias-label-secondary);',
|
|
684
713
|
'border:1px solid var(--dsw-alias-border-l1);border-radius:999px;padding:1px 8px;}'
|
|
685
714
|
].join('');
|
|
@@ -1216,16 +1245,44 @@ window.__ModuleLoader__.load({
|
|
|
1216
1245
|
}));
|
|
1217
1246
|
}
|
|
1218
1247
|
|
|
1248
|
+
|
|
1249
|
+
/** Sidebar glyph: Lucide `keyboard` (ISC) - https://lucide.dev/icons/keyboard */
|
|
1219
1250
|
function PanelIcon({ size, active }) {
|
|
1220
1251
|
const px = size ?? 16;
|
|
1221
|
-
const
|
|
1252
|
+
const dot = (d) => h('path', { key: d, d });
|
|
1253
|
+
return h('svg', {
|
|
1254
|
+
width: px,
|
|
1255
|
+
height: px,
|
|
1256
|
+
viewBox: '0 0 24 24',
|
|
1257
|
+
fill: 'none',
|
|
1258
|
+
stroke: 'currentColor',
|
|
1259
|
+
strokeWidth: 2,
|
|
1260
|
+
strokeLinecap: 'round',
|
|
1261
|
+
strokeLinejoin: 'round',
|
|
1262
|
+
'aria-hidden': true,
|
|
1263
|
+
style: { display: 'block', color: active ? 'var(--dsw-alias-state-business-primary)' : undefined }
|
|
1264
|
+
},
|
|
1265
|
+
h('rect', { key: 'frame', x: 2, y: 4, width: 20, height: 16, rx: 2 }),
|
|
1266
|
+
dot('M6 8h.01'),
|
|
1267
|
+
dot('M10 8h.01'),
|
|
1268
|
+
dot('M14 8h.01'),
|
|
1269
|
+
dot('M18 8h.01'),
|
|
1270
|
+
dot('M8 12h.01'),
|
|
1271
|
+
dot('M12 12h.01'),
|
|
1272
|
+
dot('M16 12h.01'),
|
|
1273
|
+
dot('M7 16h10'));
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
/** Lucide `rotate-ccw` (ISC) - restore a command's default binding. */
|
|
1278
|
+
function ResetIcon() {
|
|
1222
1279
|
return h('svg', {
|
|
1223
|
-
width:
|
|
1224
|
-
|
|
1280
|
+
width: 14, height: 14, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
|
|
1281
|
+
strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true,
|
|
1282
|
+
style: { display: 'block' }
|
|
1225
1283
|
},
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
bar(11, 10));
|
|
1284
|
+
h('path', { d: 'M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8' }),
|
|
1285
|
+
h('path', { d: 'M3 3v5h5' }));
|
|
1229
1286
|
}
|
|
1230
1287
|
|
|
1231
1288
|
/* ------------------------------------------------------------------ */
|
|
@@ -1407,11 +1464,11 @@ window.__ModuleLoader__.load({
|
|
|
1407
1464
|
? h('div', { className: 'dqs-status' }, t('palette.providerFailures'))
|
|
1408
1465
|
: null,
|
|
1409
1466
|
h('div', { className: 'dqs-footer' },
|
|
1410
|
-
h('span',
|
|
1411
|
-
h('span',
|
|
1412
|
-
h('span',
|
|
1413
|
-
h('span',
|
|
1414
|
-
h('span',
|
|
1467
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, '\u2191\u2193'), t('palette.hint.nav')),
|
|
1468
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, 'Enter'), t('palette.hint.confirm')),
|
|
1469
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, 'Esc'), t('palette.hint.close')),
|
|
1470
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, '\u2605'), t('palette.hint.pin')),
|
|
1471
|
+
h('span', { className: 'dqs-hintItem' }, t('palette.hint.tag')))
|
|
1415
1472
|
));
|
|
1416
1473
|
}
|
|
1417
1474
|
|
|
@@ -1618,9 +1675,9 @@ window.__ModuleLoader__.load({
|
|
|
1618
1675
|
})))),
|
|
1619
1676
|
error ? h('div', { className: 'dqs-status dqs-statusError' }, error) : null,
|
|
1620
1677
|
h('div', { className: 'dqs-footer' },
|
|
1621
|
-
h('span',
|
|
1622
|
-
h('span',
|
|
1623
|
-
h('span',
|
|
1678
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, '\u2191\u2193'), t('session.hint.nav')),
|
|
1679
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, 'Enter'), t('session.hint.open')),
|
|
1680
|
+
h('span', { className: 'dqs-hintItem' }, h('span', { className: 'dqs-kbd' }, 'Esc'), t('session.hint.close')))));
|
|
1624
1681
|
}
|
|
1625
1682
|
|
|
1626
1683
|
/* ------------------------------------------------------------------ */
|
|
@@ -1638,6 +1695,109 @@ window.__ModuleLoader__.load({
|
|
|
1638
1695
|
return h('div', { className: 'dqs-hintbar', role: 'status' }, state.text);
|
|
1639
1696
|
}
|
|
1640
1697
|
|
|
1698
|
+
/* ------------------------------------------------------------------ */
|
|
1699
|
+
/* Conversation header chips: workspace name and git branch */
|
|
1700
|
+
/* ------------------------------------------------------------------ */
|
|
1701
|
+
|
|
1702
|
+
const FOLDER_GLYPH = '<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />';
|
|
1703
|
+
const BRANCH_GLYPH = '<line x1="6" x2="6" y1="3" y2="15" /><circle cx="18" cy="6" r="3" /><circle cx="6" cy="18" r="3" /><path d="M18 9a9 9 0 0 1-9 9" />';
|
|
1704
|
+
|
|
1705
|
+
function basenameOf(path) {
|
|
1706
|
+
return String(path ?? '').split('/').filter(Boolean).pop() ?? '';
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
function workspaceOfSession(workspacesSnap, sessionId) {
|
|
1710
|
+
for (const item of workspacesSnap?.items ?? []) {
|
|
1711
|
+
if ((item?.sessionIds ?? []).includes(sessionId)) {
|
|
1712
|
+
return { title: item.title || basenameOf(item.path), path: item.path };
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
return undefined;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
function HeaderGlyph({ markup }) {
|
|
1719
|
+
return h('svg', {
|
|
1720
|
+
width: 12, height: 12, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
|
|
1721
|
+
strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true,
|
|
1722
|
+
style: { display: 'block' },
|
|
1723
|
+
dangerouslySetInnerHTML: { __html: markup }
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
function HeaderWorkspaceChip({ ctx }) {
|
|
1728
|
+
const sessionId = useSessionId(ctx);
|
|
1729
|
+
const workspacesSnap = useWorkspacesList(ctx);
|
|
1730
|
+
const sessionsSnap = useSessionsList(ctx);
|
|
1731
|
+
let workspace = sessionId === undefined ? undefined : workspaceOfSession(workspacesSnap, sessionId);
|
|
1732
|
+
if (!workspace && sessionId !== undefined) {
|
|
1733
|
+
const cwd = sessionsSnap?.byId?.[sessionId]?.cwd;
|
|
1734
|
+
const name = basenameOf(cwd);
|
|
1735
|
+
if (name !== '') workspace = { title: name, path: cwd };
|
|
1736
|
+
}
|
|
1737
|
+
if (!workspace) return null;
|
|
1738
|
+
return h('span', { className: 'dqs-hdrChip', title: workspace.path ?? workspace.title },
|
|
1739
|
+
h('span', { className: 'dqs-hdrChipIcon' }, h(HeaderGlyph, { markup: FOLDER_GLYPH })),
|
|
1740
|
+
h('span', { className: 'dqs-hdrChipLabel' }, workspace.title));
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
/** sessionId -> branch name (or null when unavailable). */
|
|
1744
|
+
const branchCache = new Map();
|
|
1745
|
+
|
|
1746
|
+
async function readGitBranch(ctx, sessionId) {
|
|
1747
|
+
try {
|
|
1748
|
+
const response = await ctx.remote.workspaceFiles.read(
|
|
1749
|
+
sessionId, '.git/HEAD', { offset: 1 }, new AbortController().signal
|
|
1750
|
+
);
|
|
1751
|
+
// Remote calls resolve to a { ok, value } result envelope.
|
|
1752
|
+
if (response && response.ok === false) {
|
|
1753
|
+
const detail = response.error ?? {};
|
|
1754
|
+
return { branch: null, error: `${detail.code ?? 'failed'} ${detail.message ?? ''}`.trim() };
|
|
1755
|
+
}
|
|
1756
|
+
const payload = response?.value ?? response;
|
|
1757
|
+
const text = String(payload?.text ?? '');
|
|
1758
|
+
const ref = /ref:\s*refs\/heads\/(.+)/u.exec(text);
|
|
1759
|
+
if (ref) return { branch: ref[1].trim(), error: null };
|
|
1760
|
+
const trimmed = text.trim();
|
|
1761
|
+
if (trimmed === '') return { branch: null, error: 'empty .git/HEAD' };
|
|
1762
|
+
return { branch: trimmed.slice(0, 7), error: null };
|
|
1763
|
+
} catch (error) {
|
|
1764
|
+
return { branch: null, error: String(error?.message ?? error) };
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
const branchErrors = new Map();
|
|
1769
|
+
|
|
1770
|
+
function HeaderBranchChip({ ctx }) {
|
|
1771
|
+
const sessionId = useSessionId(ctx);
|
|
1772
|
+
const [state, setState] = useState({ branch: null, error: null });
|
|
1773
|
+
useEffect(() => {
|
|
1774
|
+
if (sessionId === undefined) { setState({ branch: null, error: null }); return undefined; }
|
|
1775
|
+
// Show the cached value immediately, then re-read so a branch switch
|
|
1776
|
+
// made between visits is picked up.
|
|
1777
|
+
if (branchCache.has(sessionId)) {
|
|
1778
|
+
setState({ branch: branchCache.get(sessionId), error: branchErrors.get(sessionId) ?? null });
|
|
1779
|
+
} else {
|
|
1780
|
+
setState({ branch: null, error: null });
|
|
1781
|
+
}
|
|
1782
|
+
let cancelled = false;
|
|
1783
|
+
readGitBranch(ctx, sessionId).then((value) => {
|
|
1784
|
+
if (cancelled) return;
|
|
1785
|
+
branchCache.set(sessionId, value.branch);
|
|
1786
|
+
if (value.error) branchErrors.set(sessionId, value.error);
|
|
1787
|
+
else branchErrors.delete(sessionId);
|
|
1788
|
+
setState(value);
|
|
1789
|
+
});
|
|
1790
|
+
return () => { cancelled = true; };
|
|
1791
|
+
}, [ctx, sessionId]);
|
|
1792
|
+
if (state.branch) {
|
|
1793
|
+
return h('span', { className: 'dqs-hdrChip', title: `git: ${state.branch}` },
|
|
1794
|
+
h('span', { className: 'dqs-hdrChipIcon' }, h(HeaderGlyph, { markup: BRANCH_GLYPH })),
|
|
1795
|
+
h('span', { className: 'dqs-hdrChipLabel' }, state.branch));
|
|
1796
|
+
}
|
|
1797
|
+
// Not a git repository, unreadable, or still loading: stay silent.
|
|
1798
|
+
return null;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1641
1801
|
/* ------------------------------------------------------------------ */
|
|
1642
1802
|
/* Sidebar panel: command deck */
|
|
1643
1803
|
/* ------------------------------------------------------------------ */
|
|
@@ -1648,63 +1808,40 @@ window.__ModuleLoader__.load({
|
|
|
1648
1808
|
row.keys.map((cap, index) => h('span', { key: index, className: 'dqs-keycap' }, cap)));
|
|
1649
1809
|
}
|
|
1650
1810
|
|
|
1811
|
+
/**
|
|
1812
|
+
* Command tile glyphs: Lucide icons (ISC, https://lucide.dev) rendered as
|
|
1813
|
+
* static trusted markup, stroked with the current text color.
|
|
1814
|
+
*/
|
|
1815
|
+
const COMMAND_GLYPHS = {
|
|
1816
|
+
'open-model-palette': '<rect width="16" height="16" x="4" y="4" rx="2" /> <rect width="6" height="6" x="9" y="9" rx="1" /> <path d="M15 2v2" /> <path d="M15 20v2" /> <path d="M2 15h2" /> <path d="M2 9h2" /> <path d="M20 15h2" /> <path d="M20 9h2" /> <path d="M9 2v2" /> <path d="M9 20v2" />',
|
|
1817
|
+
'open-session-palette': '<path d="M14 9a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2z" /> <path d="M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1" />',
|
|
1818
|
+
'next-session': '<path d="M5 12h14" /> <path d="m12 5 7 7-7 7" />',
|
|
1819
|
+
'prev-session': '<path d="m12 19-7-7 7-7" /> <path d="M19 12H5" />',
|
|
1820
|
+
'jump-completed': '<path d="m8 11 2 2 4-4" /> <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />',
|
|
1821
|
+
'focus-composer': '<path d="M5 4h1a3 3 0 0 1 3 3 3 3 0 0 1 3-3h1" /> <path d="M13 20h-1a3 3 0 0 1-3-3 3 3 0 0 1-3 3H5" /> <path d="M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1" /> <path d="M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7" /> <path d="M9 7v10" />',
|
|
1822
|
+
'toggle-permission': '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />',
|
|
1823
|
+
'set-permission': '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /> <path d="M12 22V2" />',
|
|
1824
|
+
'toggle-sidebar': '<rect width="18" height="18" x="3" y="3" rx="2" /> <path d="M9 3v18" />',
|
|
1825
|
+
'show-conversation': '<path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z" />',
|
|
1826
|
+
'show-deck': '<rect width="7" height="7" x="3" y="3" rx="1" /> <rect width="7" height="7" x="14" y="3" rx="1" /> <rect width="7" height="7" x="14" y="14" rx="1" /> <rect width="7" height="7" x="3" y="14" rx="1" />',
|
|
1827
|
+
'new-session': '<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" /> <path d="M12 7v6" /> <path d="M9 10h6" />'
|
|
1828
|
+
};
|
|
1829
|
+
|
|
1651
1830
|
function CommandGlyph({ id }) {
|
|
1652
|
-
const
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
return h('svg', common, h('path', {
|
|
1667
|
-
d: 'M3 8h9M8.5 4 12.5 8l-4 4', stroke: 'currentColor', strokeWidth: 1.6,
|
|
1668
|
-
strokeLinecap: 'round', strokeLinejoin: 'round', fill: 'none'
|
|
1669
|
-
}));
|
|
1670
|
-
case 'prev-session':
|
|
1671
|
-
return h('svg', common, h('path', {
|
|
1672
|
-
d: 'M13 8H4M7.5 4 3.5 8l4 4', stroke: 'currentColor', strokeWidth: 1.6,
|
|
1673
|
-
strokeLinecap: 'round', strokeLinejoin: 'round', fill: 'none'
|
|
1674
|
-
}));
|
|
1675
|
-
case 'jump-completed':
|
|
1676
|
-
return h('svg', common,
|
|
1677
|
-
h('circle', { cx: 8, cy: 8, r: 5.2, fill: 'none', stroke: 'currentColor', strokeWidth: 1.5 }),
|
|
1678
|
-
h('circle', { cx: 8, cy: 8, r: 1.8, fill: 'currentColor' }));
|
|
1679
|
-
case 'focus-composer':
|
|
1680
|
-
return h('svg', common, h('path', {
|
|
1681
|
-
d: 'M5 2.5h6M8 2.5v11M5 13.5h6', stroke: 'currentColor', strokeWidth: 1.6,
|
|
1682
|
-
strokeLinecap: 'round', fill: 'none'
|
|
1683
|
-
}));
|
|
1684
|
-
case 'toggle-sidebar':
|
|
1685
|
-
return h('svg', common,
|
|
1686
|
-
h('rect', { x: 2, y: 2.5, width: 12, height: 11, rx: 2, fill: 'none', stroke: 'currentColor', strokeWidth: 1.4 }),
|
|
1687
|
-
h('path', { d: 'M6 2.5v11', stroke: 'currentColor', strokeWidth: 1.4 }));
|
|
1688
|
-
case 'show-conversation':
|
|
1689
|
-
return h('svg', common, h('path', {
|
|
1690
|
-
d: 'M2.5 3.5h11v7h-6l-3 2.5v-2.5h-2z', fill: 'none', stroke: 'currentColor',
|
|
1691
|
-
strokeWidth: 1.4, strokeLinejoin: 'round'
|
|
1692
|
-
}));
|
|
1693
|
-
case 'show-deck':
|
|
1694
|
-
return h('svg', common, h('path', {
|
|
1695
|
-
d: 'M2.5 4h11M2.5 8h11M2.5 12h11', stroke: 'currentColor', strokeWidth: 1.6,
|
|
1696
|
-
strokeLinecap: 'round', fill: 'none'
|
|
1697
|
-
}));
|
|
1698
|
-
case 'new-session':
|
|
1699
|
-
return h('svg', common, h('path', {
|
|
1700
|
-
d: 'M8 3v10M3 8h10', stroke: 'currentColor', strokeWidth: 1.7, strokeLinecap: 'round', fill: 'none'
|
|
1701
|
-
}));
|
|
1702
|
-
default:
|
|
1703
|
-
return h('svg', common, h('path', {
|
|
1704
|
-
d: 'M8 1.6 12.6 3.4v4.2c0 3.2-2.2 5.2-4.6 6.8-2.4-1.6-4.6-3.6-4.6-6.8V3.4z',
|
|
1705
|
-
fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, strokeLinejoin: 'round'
|
|
1706
|
-
}));
|
|
1707
|
-
}
|
|
1831
|
+
const markup = COMMAND_GLYPHS[id] ?? COMMAND_GLYPHS['toggle-permission'];
|
|
1832
|
+
return h('svg', {
|
|
1833
|
+
width: 20,
|
|
1834
|
+
height: 20,
|
|
1835
|
+
viewBox: '0 0 24 24',
|
|
1836
|
+
fill: 'none',
|
|
1837
|
+
stroke: 'currentColor',
|
|
1838
|
+
strokeWidth: 2,
|
|
1839
|
+
strokeLinecap: 'round',
|
|
1840
|
+
strokeLinejoin: 'round',
|
|
1841
|
+
'aria-hidden': true,
|
|
1842
|
+
style: { display: 'block' },
|
|
1843
|
+
dangerouslySetInnerHTML: { __html: markup }
|
|
1844
|
+
});
|
|
1708
1845
|
}
|
|
1709
1846
|
|
|
1710
1847
|
function SearchIcon() {
|
|
@@ -1917,6 +2054,16 @@ window.__ModuleLoader__.load({
|
|
|
1917
2054
|
sysRows.map((row) => {
|
|
1918
2055
|
return h('div', { key: row.id, className: 'dqs-sysRow' },
|
|
1919
2056
|
h('span', { className: 'dqs-sysLabel' }, row.label),
|
|
2057
|
+
h('button', {
|
|
2058
|
+
type: 'button',
|
|
2059
|
+
className: 'dqs-iconBtn dqs-tip',
|
|
2060
|
+
'data-tip': t('system.reset'),
|
|
2061
|
+
'aria-label': t('system.reset'),
|
|
2062
|
+
'data-hidden': overrides[row.id] === undefined ? 'true' : 'false',
|
|
2063
|
+
onClick: async () => {
|
|
2064
|
+
markResult(row.id, await applyEdit({ type: 'reset', id: row.id }));
|
|
2065
|
+
}
|
|
2066
|
+
}, h(ResetIcon)),
|
|
1920
2067
|
h(KeyRecorder, {
|
|
1921
2068
|
ctx,
|
|
1922
2069
|
t,
|
|
@@ -1925,15 +2072,6 @@ window.__ModuleLoader__.load({
|
|
|
1925
2072
|
markResult(row.id, await applyEdit({ type: 'set', id: row.id, binding }));
|
|
1926
2073
|
}
|
|
1927
2074
|
}),
|
|
1928
|
-
overrides[row.id] !== undefined
|
|
1929
|
-
? h('button', {
|
|
1930
|
-
type: 'button',
|
|
1931
|
-
className: 'dqs-linkBtn',
|
|
1932
|
-
onClick: async () => {
|
|
1933
|
-
markResult(row.id, await applyEdit({ type: 'reset', id: row.id }));
|
|
1934
|
-
}
|
|
1935
|
-
}, t('system.reset'))
|
|
1936
|
-
: null,
|
|
1937
2075
|
sysIssues[row.id]
|
|
1938
2076
|
? h('span', { className: 'dqs-editorError' }, sysIssues[row.id])
|
|
1939
2077
|
: null);
|
|
@@ -2261,6 +2399,7 @@ window.__ModuleLoader__.load({
|
|
|
2261
2399
|
'shortcuts',
|
|
2262
2400
|
'remote',
|
|
2263
2401
|
'remote.permissionPresets',
|
|
2402
|
+
'remote.workspaceFiles',
|
|
2264
2403
|
'modelDirectories'
|
|
2265
2404
|
],
|
|
2266
2405
|
apply(ctx) {
|
|
@@ -2278,14 +2417,28 @@ window.__ModuleLoader__.load({
|
|
|
2278
2417
|
|
|
2279
2418
|
ctx.effect(() => {
|
|
2280
2419
|
if (typeof document === 'undefined') return undefined;
|
|
2281
|
-
|
|
2282
|
-
|
|
2420
|
+
// Upgrade an existing tag in place: after a hot reload the old tag is
|
|
2421
|
+
// still attached, and skipping it would keep stale CSS alive.
|
|
2422
|
+
const existing = document.querySelector('style[data-dqs="1"]');
|
|
2423
|
+
const style = existing ?? document.createElement('style');
|
|
2283
2424
|
style.setAttribute('data-dqs', '1');
|
|
2284
2425
|
style.textContent = CSS;
|
|
2285
|
-
document.head.appendChild(style);
|
|
2286
|
-
return () => { style.remove(); };
|
|
2426
|
+
if (!existing) document.head.appendChild(style);
|
|
2427
|
+
return () => { if (style.isConnected) style.remove(); };
|
|
2287
2428
|
}, 'shortcut-ext: styles');
|
|
2288
2429
|
|
|
2430
|
+
ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({
|
|
2431
|
+
name: 'conversation.session.header.actions',
|
|
2432
|
+
id: 'shortcut-ext.header-workspace',
|
|
2433
|
+
order: 10
|
|
2434
|
+
}, () => h(HeaderWorkspaceChip, { ctx })));
|
|
2435
|
+
|
|
2436
|
+
ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({
|
|
2437
|
+
name: 'conversation.session.header.actions',
|
|
2438
|
+
id: 'shortcut-ext.header-branch',
|
|
2439
|
+
order: 11
|
|
2440
|
+
}, () => h(HeaderBranchChip, { ctx })));
|
|
2441
|
+
|
|
2289
2442
|
ctx.slots.inject('shell.overlay', () => ctx.slots.register({
|
|
2290
2443
|
name: 'shell.overlay',
|
|
2291
2444
|
id: 'shortcut-ext-palette',
|
package/icon.svg
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
2
|
-
<rect
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
+
<rect width="32" height="32" rx="7" fill="#3559e0"/>
|
|
3
|
+
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
4
|
+
<rect x="2" y="4" width="20" height="16" rx="2"/>
|
|
5
|
+
<path d="M6 8h.01"/><path d="M10 8h.01"/><path d="M14 8h.01"/><path d="M18 8h.01"/>
|
|
6
|
+
<path d="M8 12h.01"/><path d="M12 12h.01"/><path d="M16 12h.01"/>
|
|
7
|
+
<path d="M7 16h10"/>
|
|
8
|
+
</g>
|
|
6
9
|
</svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-shortcut-extensions",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shortcut Extensions: a toggleable registry of quick-switch shortcut commands (model palette with pins, session palette with prompt preview and archived restore, recency-ordered session cycling, find-next-answered jump, focus composer, configurable permission cycling) with a sidebar control panel and a custom command editor.",
|
|
6
6
|
"keywords": [
|