claude-live 2.0.7 → 3.0.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 +30 -39
- package/bin/claude-live +0 -0
- package/client/dist/assets/AgentDemoScene-DmPViizX.js +147 -0
- package/client/dist/assets/EffectDemoScene-DiyNw7OL.js +138 -0
- package/client/dist/assets/SakuraPage-BuSWb222.js +518 -0
- package/client/dist/assets/index-D3vltDuF.js +4446 -0
- package/client/dist/assets/index-TkH4paIm.css +1 -0
- package/client/dist/index.html +2 -2
- package/package.json +14 -8
- package/server/history-reader.js +68 -0
- package/server/index.js +101 -7
- package/server/project-tree.js +178 -0
- package/server/session-scanner.js +150 -0
- package/server/transcript-parser.js +177 -0
- package/.claude-plugin/hooks/hooks.json +0 -161
- package/client/dist/assets/BufferResource-B3YcFk1L.js +0 -185
- package/client/dist/assets/CanvasRenderer-B7cP3KcG.js +0 -1
- package/client/dist/assets/Filter-BXkJkOCD.js +0 -1
- package/client/dist/assets/RenderTargetSystem-DkV5EZ2H.js +0 -172
- package/client/dist/assets/WebGLRenderer-Cgmusykq.js +0 -156
- package/client/dist/assets/WebGPURenderer-B_Gw9-ml.js +0 -41
- package/client/dist/assets/browserAll-wXmCMyRg.js +0 -14
- package/client/dist/assets/index-BGs_09Jl.js +0 -318
- package/client/dist/assets/index-DjcKbX6b.css +0 -1
- package/client/dist/assets/webworkerAll-Hyzs6HuJ.js +0 -83
- package/hooks/hooks.json +0 -161
- package/hooks/run-hook.cmd +0 -38
- package/hooks/send-event +0 -5
- package/hooks/session-start +0 -40
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import"https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500&family=Space+Mono:wght@400;700&display=swap";*{margin:0;padding:0;box-sizing:border-box}html,body,#root{width:100%;height:100%;overflow:hidden;background:#050507}#root{position:relative}#root:before{content:"";position:fixed;top:0;right:0;bottom:0;left:0;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='1'/%3E%3C/svg%3E");background-size:150px;opacity:.035;pointer-events:none;z-index:10}.hud{position:fixed;top:24px;left:24px;z-index:20;font-family:Space Mono,monospace;pointer-events:none}.hud-title{font-size:17px;font-weight:700;color:#fff;letter-spacing:-.5px;margin-bottom:14px;line-height:1}.hud-title span{color:#4ade80}.hud-stat{display:flex;align-items:baseline;gap:8px;margin-bottom:5px}.hud-label{font-size:9px;color:#666;text-transform:uppercase;letter-spacing:1px;width:52px}.hud-value{font-size:13px;color:#ccc}.hud-tool{font-weight:700}.tooltip{position:fixed;z-index:30;background:#08080ef0;border:1px solid rgba(255,255,255,.12);border-radius:6px;padding:10px 14px;pointer-events:none;transition:opacity .1s ease;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);min-width:160px;box-shadow:0 8px 32px #000000b3}.tooltip-label{font-family:Fira Code,monospace;font-size:12px;color:#fff;font-weight:500;margin-bottom:2px;white-space:nowrap;max-width:260px;overflow:hidden;text-overflow:ellipsis}.tooltip-type{font-family:Space Mono,monospace;font-size:9px;color:#888;text-transform:uppercase;letter-spacing:1px;margin-bottom:7px}.tooltip-meta{font-family:Space Mono,monospace;font-size:10px;color:#aaa;margin-bottom:3px}.tooltip-count{font-family:Space Mono,monospace;font-size:9px;color:#666}.sidebar{position:fixed;right:0;top:0;height:100%;width:280px;background:#06060bf5;border-left:1px solid rgba(255,255,255,.08);z-index:25;transform:translate(100%);transition:transform .25s cubic-bezier(.16,1,.3,1);-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);display:flex;flex-direction:column;overflow:hidden}.sidebar--open{transform:translate(0)}.sidebar-header{padding:24px 20px 16px;border-bottom:1px solid rgba(255,255,255,.06);position:relative}.sidebar-close{position:absolute;top:20px;right:16px;width:26px;height:26px;display:flex;align-items:center;justify-content:center;color:#666;cursor:pointer;font-size:18px;border-radius:4px;transition:color .15s,background .15s;pointer-events:all;line-height:1}.sidebar-close:hover{color:#fff;background:#ffffff14}.sidebar-title{font-family:Fira Code,monospace;font-size:13px;color:#fff;font-weight:500;margin-bottom:4px;padding-right:32px;word-break:break-all}.sidebar-type{font-family:Space Mono,monospace;font-size:9px;color:#666;text-transform:uppercase;letter-spacing:1px}.sidebar-section{padding:16px 20px;border-bottom:1px solid rgba(255,255,255,.05)}.sidebar-section-label{font-family:Space Mono,monospace;font-size:9px;color:#555;text-transform:uppercase;letter-spacing:1px;margin-bottom:8px}.sidebar-action{font-family:Fira Code,monospace;font-size:15px;font-weight:500;margin-bottom:3px}.sidebar-time{font-family:Space Mono,monospace;font-size:10px;color:#777}.sidebar-count{font-family:Space Mono,monospace;font-size:24px;color:#ccc;font-weight:700}.sidebar-session{font-family:Fira Code,monospace;font-size:11px;color:#4ade80}.perm-badge{display:inline-flex;align-items:center;gap:5px;font-family:Space Mono,monospace;font-size:9px;color:#fbbf24;background:#fbbf241a;border:1px solid rgba(251,191,36,.3);border-radius:3px;padding:2px 6px;margin-top:6px}.perm-dot{width:5px;height:5px;border-radius:50%;background:#fbbf24;animation:perm-pulse 1s ease-in-out infinite}@keyframes perm-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}.bottom-left-panel{position:fixed;bottom:24px;left:24px;z-index:20;display:flex;flex-direction:column;gap:10px;pointer-events:none}.bottom-left-panel>*{pointer-events:all}.event-log{display:flex;flex-direction:column;gap:5px;max-width:250px}.event-log-entry{display:flex;align-items:center;gap:5px;position:relative;overflow:hidden;animation:log-entry-in .38s cubic-bezier(.16,1,.3,1)}.event-log-entry:after{content:"";position:absolute;top:0;bottom:0;left:-60%;width:60%;background:linear-gradient(90deg,transparent 0%,var(--entry-color, #888) 60%,transparent 100%);opacity:.22;animation:log-scan .55s ease-out forwards;pointer-events:none}@keyframes log-entry-in{0%{opacity:0;transform:translate(-16px)}55%{opacity:1;transform:translate(3px)}78%{transform:translate(-1px)}to{opacity:1;transform:translate(0)}}@keyframes log-scan{0%{left:-60%;opacity:.22}to{left:130%;opacity:0}}.event-log-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0;animation:log-dot-pop .42s cubic-bezier(.34,1.56,.64,1)}@keyframes log-dot-pop{0%{transform:scale(0) rotate(-90deg)}70%{transform:scale(1.5) rotate(8deg)}to{transform:scale(1) rotate(0)}}.event-log-tool{font-family:Space Mono,monospace;font-size:8px;font-weight:700;min-width:38px;text-transform:uppercase;letter-spacing:.04em;animation:log-tool-in .3s ease-out}@keyframes log-tool-in{0%{opacity:0;letter-spacing:.28em}to{opacity:1;letter-spacing:.04em}}.event-log-file{font-family:Fira Code,monospace;font-size:8px;color:#999;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100px}.event-log-session{font-family:Fira Code,monospace;font-size:7px;color:#3a3a3a;white-space:nowrap;margin-left:auto}.event-log-entry--static,.event-log-entry--static .event-log-dot,.event-log-entry--static .event-log-tool{animation:none}.event-log-entry--static:after{display:none}.event-log-history{width:280px;height:calc(100vh - 80px);overflow-y:scroll;display:flex;flex-direction:column;gap:5px;background:#020209eb;border:1px solid rgba(255,255,255,.08);border-radius:4px;padding:6px;box-sizing:border-box}.event-log-history-back{font-family:Space Mono,monospace;font-size:8px;color:#555;background:none;border:none;cursor:pointer;text-align:left;padding:0 0 4px}.event-log-history-back:hover{color:#aaa}.event-log-history-btn{font-family:Space Mono,monospace;font-size:7px;color:#333;background:none;border:none;cursor:pointer;text-align:left;padding:2px 0 0 10px}.event-log-history-btn:hover{color:#777}.help-btn{background:none;border:1px solid rgba(255,255,255,.1);border-radius:4px;color:#444;font-family:Space Mono,monospace;font-size:9px;padding:3px 8px;cursor:pointer;width:fit-content;transition:color .15s,border-color .15s;letter-spacing:.05em;text-transform:uppercase}.help-btn:hover{color:#999;border-color:#ffffff40}.top-right-buttons{position:fixed;top:24px;right:24px;z-index:50;display:flex;gap:8px;align-items:center;pointer-events:auto}.audio-toggle{background:none;border:1px solid rgba(255,255,255,.1);border-radius:4px;color:#666;cursor:pointer;transition:color .15s,border-color .15s,background-color .15s;display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;font-size:0}.audio-toggle svg{width:16px;height:16px;stroke:currentColor}.audio-toggle:hover{color:#999;border-color:#ffffff40;background-color:#ffffff0d}.audio-toggle:active{background-color:#ffffff1a}.autofit-toggle{background:none;border:1px solid rgba(255,255,255,.1);color:#ccc;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s ease;width:32px;height:32px;padding:0;font-size:0}.autofit-toggle svg{width:16px;height:16px;stroke:currentColor}.autofit-toggle:hover{color:#999;border-color:#ffffff40;background-color:#ffffff0d}.autofit-toggle:active{background-color:#ffffff1a}.hud-button{width:32px;height:32px;background:#ffffff14;border:1px solid rgba(255,255,255,.12);border-radius:4px;color:#666;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center;transition:color .2s}.hud-button:hover{color:#aaa}.help-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;background:#0000008c;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.help-panel{background:#08080efa;border:1px solid rgba(255,255,255,.1);border-radius:8px;padding:20px 24px;min-width:200px;box-shadow:0 16px 48px #000c}.help-panel-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}.help-panel-title{font-family:Space Mono,monospace;font-size:9px;color:#555;text-transform:uppercase;letter-spacing:1.5px}.legend-title{font-size:8px;color:#444;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:8px}.legend-items{display:flex;flex-direction:column;gap:5px}.legend-item{display:flex;align-items:center;gap:8px}.legend-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.legend-badge{width:14px;height:14px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:7px;font-weight:700;color:#000;flex-shrink:0}.legend-name{font-size:9px;color:#888}.legend-key{font-size:8px;color:#555;margin-left:auto;padding-left:8px}.legend-perm{display:flex;align-items:center;gap:8px;margin-top:4px;padding-top:6px;border-top:1px solid rgba(255,255,255,.04)}.legend-perm-ring{width:14px;height:14px;border-radius:50%;border:2px dashed #fbbf24;flex-shrink:0}.legend-perm-name{font-size:9px;color:#fbbf24}.debug-toggle{position:fixed;bottom:24px;right:24px;z-index:40;background:#fbbf241f;border:1px solid rgba(251,191,36,.4);border-radius:5px;color:#fbbf24e6;font-family:Space Mono,monospace;font-size:10px;font-weight:700;letter-spacing:.15em;padding:6px 12px;cursor:pointer;transition:color .15s,background .15s,border-color .15s}.debug-toggle:hover{background:#fbbf2438;border-color:#fbbf24b3;color:#fbbf24}.debug-panel{position:fixed;bottom:56px;right:24px;width:260px;background:#06060cf7;border:1px solid rgba(255,255,255,.1);border-radius:8px;z-index:40;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);box-shadow:0 16px 48px #000c;transform:translateY(8px) scale(.97);opacity:0;pointer-events:none;transition:opacity .18s ease,transform .18s ease}.debug-panel--open{opacity:1;transform:translateY(0) scale(1);pointer-events:all}.debug-panel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 14px 10px;border-bottom:1px solid rgba(255,255,255,.07)}.debug-panel-title{font-family:Space Mono,monospace;font-size:9px;color:#555;text-transform:uppercase;letter-spacing:1.5px}.debug-close{background:none;border:none;color:#555;font-size:16px;cursor:pointer;padding:0 2px;line-height:1;transition:color .15s}.debug-close:hover{color:#ccc}.debug-section{padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.05)}.debug-section:last-child{border-bottom:none}.debug-section-label{font-family:Space Mono,monospace;font-size:8px;color:#444;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:8px}.debug-session-row{display:flex;gap:6px}.debug-select{flex:1;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);border-radius:4px;color:#aaa;font-family:Fira Code,monospace;font-size:10px;padding:4px 7px;outline:none;cursor:pointer}.debug-new-btn{background:#ffffff0f;border:1px solid rgba(255,255,255,.12);border-radius:4px;color:#888;font-family:Space Mono,monospace;font-size:9px;padding:4px 8px;cursor:pointer;white-space:nowrap;transition:color .15s,background .15s}.debug-new-btn:hover{color:#ccc;background:#ffffff1a}.debug-tool-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:5px}.debug-tool-btn{background:#ffffff0a;border:1px solid rgba(255,255,255,.08);border-radius:4px;color:var(--tool-color, #888);font-family:Space Mono,monospace;font-size:9px;padding:6px 4px;cursor:pointer;transition:background .15s,border-color .15s,opacity .15s;text-align:center}.debug-tool-btn:hover{background:color-mix(in srgb,var(--tool-color, #888) 15%,transparent);border-color:color-mix(in srgb,var(--tool-color, #888) 40%,transparent)}.debug-tool-btn:active{opacity:.6}.perm-notifications{position:fixed;left:24px;top:130px;display:flex;flex-direction:column;gap:6px;z-index:100;pointer-events:none;max-width:280px}.perm-notifications-title{font-size:9px;letter-spacing:.2em;text-transform:uppercase;color:#fbbf24;text-align:left;margin-bottom:2px;opacity:.7}.perm-notification-item{display:flex;align-items:flex-start;gap:10px;background:#fbbf240f;border:1px solid rgba(251,191,36,.25);border-radius:3px;padding:8px 14px;animation:perm-fadein .3s ease}@keyframes perm-fadein{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.perm-notification-dot{width:6px;height:6px;border-radius:50%;background:#fbbf24;margin-top:3px;flex-shrink:0;animation:perm-pulse 1s ease-in-out infinite}.perm-notification-body{display:flex;flex-direction:column;gap:2px}.perm-notification-session{font-size:9px;letter-spacing:.15em;color:#fbbf2499;text-transform:uppercase}.perm-notification-msg{font-size:11px;color:#fbbf24e6;max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.panel-overlay{position:fixed;top:24px;right:24px;max-width:400px;max-height:calc(100vh - 48px);background:#020209f2;border:1px solid rgba(255,255,255,.1);border-radius:8px;padding:16px;overflow-y:auto;z-index:100;font-size:12px;line-height:1.6;color:#ccc}.panel-close,.panel-close-btn{position:absolute;top:8px;right:8px;background:none;border:none;color:#666;cursor:pointer;font-size:16px;padding:0;width:24px;height:24px}.panel-close:hover,.panel-close-btn:hover{color:#aaa}.panel-overlay h3{margin:0 0 12px;font-size:14px;font-weight:600;color:#fff}.panel-overlay h4{margin:8px 0 6px;font-size:12px;font-weight:600;color:#aaa;text-transform:uppercase;letter-spacing:.05em}.panel-section{margin-bottom:16px}.panel-section:last-child{margin-bottom:0}.node-types-grid{display:flex;flex-direction:column;gap:8px}.node-type-item{display:flex;align-items:center;gap:8px}.node-type-badge{width:28px;height:28px;border-radius:4px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;color:#fff;flex-shrink:0}.node-type-info{display:flex;flex-direction:column;gap:2px}.node-type-name{font-size:12px;font-weight:500;color:#fff}.node-type-description{font-size:10px;color:#888}.animations-list{display:flex;flex-direction:column;gap:10px}.animation-item{font-size:11px}.animation-name{font-weight:500;color:#fff;margin-bottom:2px}.animation-description{font-size:10px;color:#888;padding-left:8px;border-left:2px solid rgba(255,255,255,.1)}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import{G,b as I,i as _,M as k,K as B,z as O,$ as m,T as v,ai as A,R as C,w as z,_ as E,p as w}from"./index-BGs_09Jl.js";import{F as U}from"./Filter-BXkJkOCD.js";var M=`in vec2 aPosition;
|
|
2
|
-
out vec2 vTextureCoord;
|
|
3
|
-
|
|
4
|
-
uniform vec4 uInputSize;
|
|
5
|
-
uniform vec4 uOutputFrame;
|
|
6
|
-
uniform vec4 uOutputTexture;
|
|
7
|
-
|
|
8
|
-
vec4 filterVertexPosition( void )
|
|
9
|
-
{
|
|
10
|
-
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
11
|
-
|
|
12
|
-
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
13
|
-
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
14
|
-
|
|
15
|
-
return vec4(position, 0.0, 1.0);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
vec2 filterTextureCoord( void )
|
|
19
|
-
{
|
|
20
|
-
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
void main(void)
|
|
24
|
-
{
|
|
25
|
-
gl_Position = filterVertexPosition();
|
|
26
|
-
vTextureCoord = filterTextureCoord();
|
|
27
|
-
}
|
|
28
|
-
`,V=`in vec2 vTextureCoord;
|
|
29
|
-
out vec4 finalColor;
|
|
30
|
-
uniform sampler2D uTexture;
|
|
31
|
-
void main() {
|
|
32
|
-
finalColor = texture(uTexture, vTextureCoord);
|
|
33
|
-
}
|
|
34
|
-
`,y=`struct GlobalFilterUniforms {
|
|
35
|
-
uInputSize: vec4<f32>,
|
|
36
|
-
uInputPixel: vec4<f32>,
|
|
37
|
-
uInputClamp: vec4<f32>,
|
|
38
|
-
uOutputFrame: vec4<f32>,
|
|
39
|
-
uGlobalFrame: vec4<f32>,
|
|
40
|
-
uOutputTexture: vec4<f32>,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
@group(0) @binding(0) var <uniform> gfu: GlobalFilterUniforms;
|
|
44
|
-
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
|
45
|
-
@group(0) @binding(2) var uSampler: sampler;
|
|
46
|
-
|
|
47
|
-
struct VSOutput {
|
|
48
|
-
@builtin(position) position: vec4<f32>,
|
|
49
|
-
@location(0) uv: vec2<f32>
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
fn filterVertexPosition(aPosition: vec2<f32>) -> vec4<f32>
|
|
53
|
-
{
|
|
54
|
-
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
|
55
|
-
|
|
56
|
-
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
|
57
|
-
position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
|
58
|
-
|
|
59
|
-
return vec4(position, 0.0, 1.0);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
fn filterTextureCoord(aPosition: vec2<f32>) -> vec2<f32>
|
|
63
|
-
{
|
|
64
|
-
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
@vertex
|
|
68
|
-
fn mainVertex(
|
|
69
|
-
@location(0) aPosition: vec2<f32>,
|
|
70
|
-
) -> VSOutput {
|
|
71
|
-
return VSOutput(
|
|
72
|
-
filterVertexPosition(aPosition),
|
|
73
|
-
filterTextureCoord(aPosition)
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
@fragment
|
|
78
|
-
fn mainFragment(
|
|
79
|
-
@location(0) uv: vec2<f32>,
|
|
80
|
-
) -> @location(0) vec4<f32> {
|
|
81
|
-
return textureSample(uTexture, uSampler, uv);
|
|
82
|
-
}
|
|
83
|
-
`;class Y extends U{constructor(){const e=G.from({vertex:{source:y,entryPoint:"mainVertex"},fragment:{source:y,entryPoint:"mainFragment"},name:"passthrough-filter"}),t=I.from({vertex:M,fragment:V,name:"passthrough-filter"});super({gpuProgram:e,glProgram:t})}}class R{constructor(e){this._renderer=e}push(e,t,r){this._renderer.renderPipes.batch.break(r),r.add({renderPipeId:"filter",canBundle:!1,action:"pushFilter",container:t,filterEffect:e})}pop(e,t,r){this._renderer.renderPipes.batch.break(r),r.add({renderPipeId:"filter",action:"popFilter",canBundle:!1})}execute(e){e.action==="pushFilter"?this._renderer.filter.push(e):e.action==="popFilter"&&this._renderer.filter.pop()}destroy(){this._renderer=null}}R.extension={type:[_.WebGLPipes,_.WebGPUPipes,_.CanvasPipes],name:"filter"};const P=new k;function X(T,e){e.clear();const t=e.matrix;for(let r=0;r<T.length;r++){const n=T[r];if(n.globalDisplayStatus<7)continue;const i=n.renderGroup??n.parentRenderGroup;i!=null&&i.isCachedAsTexture?e.matrix=P.copyFrom(i.textureOffsetInverseTransform).append(n.worldTransform):i!=null&&i._parentCacheAsTextureRenderGroup?e.matrix=P.copyFrom(i._parentCacheAsTextureRenderGroup.inverseWorldTransform).append(n.groupTransform):e.matrix=n.worldTransform,e.addBounds(n.bounds)}return e.matrix=t,e}const q=new A({attributes:{aPosition:{buffer:new Float32Array([0,0,1,0,1,1,0,1]),format:"float32x2",stride:2*4,offset:0}},indexBuffer:new Uint32Array([0,1,2,0,2,3])});class W{constructor(){this.skip=!1,this.inputTexture=null,this.backTexture=null,this.filters=null,this.bounds=new E,this.container=null,this.blendRequired=!1,this.outputRenderSurface=null,this.globalFrame={x:0,y:0,width:0,height:0},this.firstEnabledIndex=-1,this.lastEnabledIndex=-1}}class S{constructor(e){this._filterStackIndex=0,this._filterStack=[],this._filterGlobalUniforms=new B({uInputSize:{value:new Float32Array(4),type:"vec4<f32>"},uInputPixel:{value:new Float32Array(4),type:"vec4<f32>"},uInputClamp:{value:new Float32Array(4),type:"vec4<f32>"},uOutputFrame:{value:new Float32Array(4),type:"vec4<f32>"},uGlobalFrame:{value:new Float32Array(4),type:"vec4<f32>"},uOutputTexture:{value:new Float32Array(4),type:"vec4<f32>"}}),this._globalFilterBindGroup=new O({}),this.renderer=e}get activeBackTexture(){var e;return(e=this._activeFilterData)==null?void 0:e.backTexture}push(e){const t=this.renderer,r=e.filterEffect.filters,n=this._pushFilterData();n.skip=!1,n.filters=r,n.container=e.container,n.outputRenderSurface=t.renderTarget.renderSurface;const i=t.renderTarget.renderTarget.colorTexture.source,o=i.resolution,s=i.antialias;if(r.every(d=>!d.enabled)){n.skip=!0;return}const c=n.bounds;if(this._calculateFilterArea(e,c),this._calculateFilterBounds(n,t.renderTarget.rootViewPort,s,o,1),n.skip)return;const u=this._getPreviousFilterData(),f=this._findFilterResolution(o);let l=0,a=0;u&&(l=u.bounds.minX,a=u.bounds.minY),this._calculateGlobalFrame(n,l,a,f,i.width,i.height),this._setupFilterTextures(n,c,t,u)}generateFilteredTexture({texture:e,filters:t}){const r=this._pushFilterData();this._activeFilterData=r,r.skip=!1,r.filters=t;const n=e.source,i=n.resolution,o=n.antialias;if(t.every(d=>!d.enabled))return r.skip=!0,e;const s=r.bounds;if(s.addRect(e.frame),this._calculateFilterBounds(r,s.rectangle,o,i,0),r.skip)return e;const c=i;this._calculateGlobalFrame(r,0,0,c,n.width,n.height),r.outputRenderSurface=m.getOptimalTexture(s.width,s.height,r.resolution,r.antialias),r.backTexture=v.EMPTY,r.inputTexture=e,this.renderer.renderTarget.finishRenderPass(),this._applyFiltersToTexture(r,!0);const a=r.outputRenderSurface;return a.source.alphaMode="premultiplied-alpha",a}pop(){const e=this.renderer,t=this._popFilterData();t.skip||(e.globalUniforms.pop(),e.renderTarget.finishRenderPass(),this._activeFilterData=t,this._applyFiltersToTexture(t,!1),t.blendRequired&&m.returnTexture(t.backTexture),m.returnTexture(t.inputTexture))}getBackTexture(e,t,r){const n=e.colorTexture.source._resolution,i=m.getOptimalTexture(t.width,t.height,n,!1);let o=t.minX,s=t.minY;r&&(o-=r.minX,s-=r.minY),o=Math.floor(o*n),s=Math.floor(s*n);const c=Math.ceil(t.width*n),u=Math.ceil(t.height*n);return this.renderer.renderTarget.copyToTexture(e,i,{x:o,y:s},{width:c,height:u},{x:0,y:0}),i}applyFilter(e,t,r,n){const i=this.renderer,o=this._activeFilterData,c=o.outputRenderSurface===r,u=i.renderTarget.rootRenderTarget.colorTexture.source._resolution,f=this._findFilterResolution(u);let l=0,a=0;if(c){const p=this._findPreviousFilterOffset();l=p.x,a=p.y}this._updateFilterUniforms(t,r,o,l,a,f,c,n);const d=e.enabled?e:this._getPassthroughFilter();this._setupBindGroupsAndRender(d,t,i)}calculateSpriteMatrix(e,t){const r=this._activeFilterData,n=e.set(r.inputTexture._source.width,0,0,r.inputTexture._source.height,r.bounds.minX,r.bounds.minY),i=t.worldTransform.copyTo(k.shared),o=t.renderGroup||t.parentRenderGroup;return o&&o.cacheToLocalTransform&&i.prepend(o.cacheToLocalTransform),i.invert(),n.prepend(i),n.scale(1/t.texture.orig.width,1/t.texture.orig.height),n.translate(t.anchor.x,t.anchor.y),n}destroy(){var e;(e=this._passthroughFilter)==null||e.destroy(!0),this._passthroughFilter=null}_getPassthroughFilter(){return this._passthroughFilter??(this._passthroughFilter=new Y),this._passthroughFilter}_setupBindGroupsAndRender(e,t,r){if(r.renderPipes.uniformBatch){const n=r.renderPipes.uniformBatch.getUboResource(this._filterGlobalUniforms);this._globalFilterBindGroup.setResource(n,0)}else this._globalFilterBindGroup.setResource(this._filterGlobalUniforms,0);this._globalFilterBindGroup.setResource(t.source,1),this._globalFilterBindGroup.setResource(t.source.style,2),e.groups[0]=this._globalFilterBindGroup,r.encoder.draw({geometry:q,shader:e,state:e._state,topology:"triangle-list"}),r.type===C.WEBGL&&r.renderTarget.finishRenderPass()}_setupFilterTextures(e,t,r,n){if(e.backTexture=v.EMPTY,e.inputTexture=m.getOptimalTexture(t.width,t.height,e.resolution,e.antialias),e.blendRequired){r.renderTarget.finishRenderPass();const i=r.renderTarget.getRenderTarget(e.outputRenderSurface);e.backTexture=this.getBackTexture(i,t,n==null?void 0:n.bounds)}r.renderTarget.bind(e.inputTexture,!0),r.globalUniforms.push({offset:t})}_calculateGlobalFrame(e,t,r,n,i,o){const s=e.globalFrame;s.x=t*n,s.y=r*n,s.width=i*n,s.height=o*n}_updateFilterUniforms(e,t,r,n,i,o,s,c){const u=this._filterGlobalUniforms.uniforms,f=u.uOutputFrame,l=u.uInputSize,a=u.uInputPixel,d=u.uInputClamp,p=u.uGlobalFrame,x=u.uOutputTexture;s?(f[0]=r.bounds.minX-n,f[1]=r.bounds.minY-i):(f[0]=0,f[1]=0),f[2]=e.frame.width,f[3]=e.frame.height,l[0]=e.source.width,l[1]=e.source.height,l[2]=1/l[0],l[3]=1/l[1],a[0]=e.source.pixelWidth,a[1]=e.source.pixelHeight,a[2]=1/a[0],a[3]=1/a[1],d[0]=.5*a[2],d[1]=.5*a[3],d[2]=e.frame.width*l[2]-.5*a[2],d[3]=e.frame.height*l[3]-.5*a[3];const b=this.renderer.renderTarget.rootRenderTarget.colorTexture;p[0]=n*o,p[1]=i*o,p[2]=b.source.width*o,p[3]=b.source.height*o,t instanceof v&&(t.source.resource=null);const g=this.renderer.renderTarget.getRenderTarget(t);this.renderer.renderTarget.bind(t,!!c),t instanceof v?(x[0]=t.frame.width,x[1]=t.frame.height):(x[0]=g.width,x[1]=g.height),x[2]=g.isRoot?-1:1,this._filterGlobalUniforms.update()}_findFilterResolution(e){let t=this._filterStackIndex-1;for(;t>0&&this._filterStack[t].skip;)--t;return t>0&&this._filterStack[t].inputTexture?this._filterStack[t].inputTexture.source._resolution:e}_findPreviousFilterOffset(){let e=0,t=0,r=this._filterStackIndex;for(;r>0;){r--;const n=this._filterStack[r];if(!n.skip){e=n.bounds.minX,t=n.bounds.minY;break}}return{x:e,y:t}}_calculateFilterArea(e,t){if(e.renderables?X(e.renderables,t):e.filterEffect.filterArea?(t.clear(),t.addRect(e.filterEffect.filterArea),t.applyMatrix(e.container.worldTransform)):e.container.getFastGlobalBounds(!0,t),e.container){const n=(e.container.renderGroup||e.container.parentRenderGroup).cacheToLocalTransform;n&&t.applyMatrix(n)}}_applyFiltersToTexture(e,t){const r=e.inputTexture,n=e.bounds,i=e.filters,o=e.firstEnabledIndex,s=e.lastEnabledIndex;if(this._globalFilterBindGroup.setResource(r.source.style,2),this._globalFilterBindGroup.setResource(e.backTexture.source,3),o===s)i[o].apply(this,r,e.outputRenderSurface,t);else{let c=e.inputTexture;const u=m.getOptimalTexture(n.width,n.height,c.source._resolution,!1);let f=u;for(let l=o;l<s;l++){const a=i[l];if(!a.enabled)continue;a.apply(this,c,f,!0);const d=c;c=f,f=d}i[s].apply(this,c,e.outputRenderSurface,t),m.returnTexture(u)}}_calculateFilterBounds(e,t,r,n,i){var g;const o=this.renderer,s=e.bounds,c=e.filters;let u=1/0,f=0,l=!0,a=!1,d=!1,p=!0,x=-1,b=-1;for(let F=0;F<c.length;F++){const h=c[F];if(!h.enabled)continue;if(x===-1&&(x=F),b=F,u=Math.min(u,h.resolution==="inherit"?n:h.resolution),f+=h.padding,h.antialias==="off"?l=!1:h.antialias==="inherit"&&l&&(l=r),h.clipToViewport||(p=!1),!!!(h.compatibleRenderers&o.type)){d=!1;break}if(h.blendRequired&&!(((g=o.backBuffer)==null?void 0:g.useBackBuffer)??!0)){z("Blend filter requires backBuffer on WebGL renderer to be enabled. Set `useBackBuffer: true` in the renderer options."),d=!1;break}d=!0,a||(a=h.blendRequired)}if(!d){e.skip=!0;return}if(p&&s.fitBounds(0,t.width/n,0,t.height/n),s.scale(u).ceil().scale(1/u).pad((f|0)*i),!s.isPositive){e.skip=!0;return}e.antialias=l,e.resolution=u,e.blendRequired=a,e.firstEnabledIndex=x,e.lastEnabledIndex=b}_popFilterData(){return this._filterStackIndex--,this._filterStack[this._filterStackIndex]}_getPreviousFilterData(){let e,t=this._filterStackIndex-1;for(;t>0&&(t--,e=this._filterStack[t],!!e.skip););return e}_pushFilterData(){let e=this._filterStack[this._filterStackIndex];return e||(e=this._filterStack[this._filterStackIndex]=new W),this._filterStackIndex++,e}}S.extension={type:[_.WebGLSystem,_.WebGPUSystem],name:"filter"};w.add(S);w.add(R);
|
package/hooks/hooks.json
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"description": "claude-live hooks — forwards Claude Code events to the visualizer",
|
|
3
|
-
"hooks": {
|
|
4
|
-
"SessionStart": [{
|
|
5
|
-
"hooks": [{
|
|
6
|
-
"type": "command",
|
|
7
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
8
|
-
"async": true
|
|
9
|
-
}]
|
|
10
|
-
}],
|
|
11
|
-
"InstructionsLoaded": [{
|
|
12
|
-
"hooks": [{
|
|
13
|
-
"type": "command",
|
|
14
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
15
|
-
"async": true
|
|
16
|
-
}]
|
|
17
|
-
}],
|
|
18
|
-
"WorktreeCreate": [{
|
|
19
|
-
"hooks": [{
|
|
20
|
-
"type": "command",
|
|
21
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
22
|
-
"async": true
|
|
23
|
-
}]
|
|
24
|
-
}],
|
|
25
|
-
"WorktreeRemove": [{
|
|
26
|
-
"hooks": [{
|
|
27
|
-
"type": "command",
|
|
28
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
29
|
-
"async": true
|
|
30
|
-
}]
|
|
31
|
-
}],
|
|
32
|
-
"PreToolUse": [{
|
|
33
|
-
"hooks": [{
|
|
34
|
-
"type": "command",
|
|
35
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
36
|
-
"async": true
|
|
37
|
-
}]
|
|
38
|
-
}],
|
|
39
|
-
"PostToolUse": [{
|
|
40
|
-
"hooks": [{
|
|
41
|
-
"type": "command",
|
|
42
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
43
|
-
"async": true
|
|
44
|
-
}]
|
|
45
|
-
}],
|
|
46
|
-
"Stop": [{
|
|
47
|
-
"hooks": [{
|
|
48
|
-
"type": "command",
|
|
49
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
50
|
-
"async": true
|
|
51
|
-
}]
|
|
52
|
-
}],
|
|
53
|
-
"Notification": [{
|
|
54
|
-
"hooks": [{
|
|
55
|
-
"type": "command",
|
|
56
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
57
|
-
"async": true
|
|
58
|
-
}]
|
|
59
|
-
}],
|
|
60
|
-
"PermissionRequest": [{
|
|
61
|
-
"hooks": [{
|
|
62
|
-
"type": "command",
|
|
63
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
64
|
-
"async": true
|
|
65
|
-
}]
|
|
66
|
-
}],
|
|
67
|
-
"SubagentStart": [{
|
|
68
|
-
"hooks": [{
|
|
69
|
-
"type": "command",
|
|
70
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
71
|
-
"async": true
|
|
72
|
-
}]
|
|
73
|
-
}],
|
|
74
|
-
"SubagentStop": [{
|
|
75
|
-
"hooks": [{
|
|
76
|
-
"type": "command",
|
|
77
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
78
|
-
"async": true
|
|
79
|
-
}]
|
|
80
|
-
}],
|
|
81
|
-
"SessionEnd": [{
|
|
82
|
-
"hooks": [{
|
|
83
|
-
"type": "command",
|
|
84
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
85
|
-
"async": true
|
|
86
|
-
}]
|
|
87
|
-
}],
|
|
88
|
-
"PostToolUseFailure": [{
|
|
89
|
-
"hooks": [{
|
|
90
|
-
"type": "command",
|
|
91
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
92
|
-
"async": true
|
|
93
|
-
}]
|
|
94
|
-
}],
|
|
95
|
-
"UserPromptSubmit": [{
|
|
96
|
-
"hooks": [{
|
|
97
|
-
"type": "command",
|
|
98
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
99
|
-
"async": true
|
|
100
|
-
}]
|
|
101
|
-
}],
|
|
102
|
-
"PreCompact": [{
|
|
103
|
-
"match": { "trigger": ["manual", "auto"] },
|
|
104
|
-
"hooks": [{
|
|
105
|
-
"type": "command",
|
|
106
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
107
|
-
"async": true
|
|
108
|
-
}]
|
|
109
|
-
}],
|
|
110
|
-
"PostCompact": [{
|
|
111
|
-
"match": { "trigger": ["manual", "auto"] },
|
|
112
|
-
"hooks": [{
|
|
113
|
-
"type": "command",
|
|
114
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
115
|
-
"async": true
|
|
116
|
-
}]
|
|
117
|
-
}],
|
|
118
|
-
"StopFailure": [{
|
|
119
|
-
"hooks": [{
|
|
120
|
-
"type": "command",
|
|
121
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
122
|
-
"async": true
|
|
123
|
-
}]
|
|
124
|
-
}],
|
|
125
|
-
"TeammateIdle": [{
|
|
126
|
-
"hooks": [{
|
|
127
|
-
"type": "command",
|
|
128
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
129
|
-
"async": true
|
|
130
|
-
}]
|
|
131
|
-
}],
|
|
132
|
-
"TaskCompleted": [{
|
|
133
|
-
"hooks": [{
|
|
134
|
-
"type": "command",
|
|
135
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
136
|
-
"async": true
|
|
137
|
-
}]
|
|
138
|
-
}],
|
|
139
|
-
"ConfigChange": [{
|
|
140
|
-
"hooks": [{
|
|
141
|
-
"type": "command",
|
|
142
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
143
|
-
"async": true
|
|
144
|
-
}]
|
|
145
|
-
}],
|
|
146
|
-
"Elicitation": [{
|
|
147
|
-
"hooks": [{
|
|
148
|
-
"type": "command",
|
|
149
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
150
|
-
"async": true
|
|
151
|
-
}]
|
|
152
|
-
}],
|
|
153
|
-
"ElicitationResult": [{
|
|
154
|
-
"hooks": [{
|
|
155
|
-
"type": "command",
|
|
156
|
-
"command": "node ${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/claude-live}/bin/hook.js",
|
|
157
|
-
"async": true
|
|
158
|
-
}]
|
|
159
|
-
}]
|
|
160
|
-
}
|
|
161
|
-
}
|
package/hooks/run-hook.cmd
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
: << 'CMDBLOCK'
|
|
2
|
-
@echo off
|
|
3
|
-
REM Cross-platform polyglot wrapper for hook scripts.
|
|
4
|
-
REM On Windows: cmd.exe runs the batch portion.
|
|
5
|
-
REM On Unix: the shell interprets this as a script (: is a no-op).
|
|
6
|
-
|
|
7
|
-
if "%~1"=="" (
|
|
8
|
-
echo run-hook.cmd: missing script name >&2
|
|
9
|
-
exit /b 1
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
set "HOOK_DIR=%~dp0"
|
|
13
|
-
|
|
14
|
-
if exist "C:\Program Files\Git\bin\bash.exe" (
|
|
15
|
-
"C:\Program Files\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
|
|
16
|
-
exit /b %ERRORLEVEL%
|
|
17
|
-
)
|
|
18
|
-
if exist "C:\Program Files (x86)\Git\bin\bash.exe" (
|
|
19
|
-
"C:\Program Files (x86)\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
|
|
20
|
-
exit /b %ERRORLEVEL%
|
|
21
|
-
)
|
|
22
|
-
where bash >nul 2>nul
|
|
23
|
-
if %ERRORLEVEL% equ 0 (
|
|
24
|
-
bash "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
|
|
25
|
-
exit /b %ERRORLEVEL%
|
|
26
|
-
)
|
|
27
|
-
exit /b 0
|
|
28
|
-
CMDBLOCK
|
|
29
|
-
|
|
30
|
-
# Unix: run the named script directly
|
|
31
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
32
|
-
if [ -z "${1:-}" ]; then
|
|
33
|
-
echo "run-hook.cmd: missing script name" >&2
|
|
34
|
-
exit 1
|
|
35
|
-
fi
|
|
36
|
-
SCRIPT_NAME="$1"
|
|
37
|
-
shift
|
|
38
|
-
exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"
|
package/hooks/send-event
DELETED
package/hooks/session-start
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SessionStart hook: auto-starts claude-live server if not running, then forwards event.
|
|
3
|
-
set -euo pipefail
|
|
4
|
-
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
-
PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
7
|
-
SERVER="${PLUGIN_ROOT}/server/index.js"
|
|
8
|
-
LOG="/tmp/claude-live.log"
|
|
9
|
-
PORT="${CLAUDE_LIVE_PORT:-43451}"
|
|
10
|
-
|
|
11
|
-
# Read stdin so it's available to forward
|
|
12
|
-
input="$(cat)"
|
|
13
|
-
|
|
14
|
-
# Check if server is already running.
|
|
15
|
-
# /events is an SSE stream that never closes, so curl exits with 28 (timeout) on success.
|
|
16
|
-
# We treat exit 0 (got data + closed) and 28 (timeout = streaming) as "server up".
|
|
17
|
-
server_up() {
|
|
18
|
-
local code
|
|
19
|
-
curl -s "http://127.0.0.1:${PORT}/events" -o /dev/null -m 1 2>/dev/null
|
|
20
|
-
code=$?
|
|
21
|
-
[ "$code" -eq 0 ] || [ "$code" -eq 28 ]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if ! server_up; then
|
|
25
|
-
# Start server detached
|
|
26
|
-
nohup node "${SERVER}" >"${LOG}" 2>&1 &
|
|
27
|
-
disown
|
|
28
|
-
# Wait up to 3s for it to come up
|
|
29
|
-
for i in 1 2 3; do
|
|
30
|
-
sleep 1
|
|
31
|
-
server_up && break
|
|
32
|
-
done
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
# Forward event to server (if it came up)
|
|
36
|
-
if [ -n "$input" ]; then
|
|
37
|
-
printf '%s' "$input" | node "${PLUGIN_ROOT}/bin/hook.js" || true
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
exit 0
|