@kortix/sandbox 0.4.1 → 0.4.3
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/config/customize.sh +92 -105
- package/config/kortix-env-setup.sh +5 -5
- package/kortix-master/src/index.ts +12 -2
- package/kortix-master/src/routes/update.ts +23 -66
- package/opencode/skills/KORTIX-cron-triggers/SKILL.md +19 -19
- package/opencode/skills/KORTIX-deploy/SKILL.md +438 -0
- package/opencode/skills/KORTIX-deploy/references/freestyle-api.md +279 -0
- package/package.json +1 -1
- package/patch-agent-browser.js +10 -3
- package/services/KORTIX-presentation-viewer/run +0 -37
- package/services/agent-browser-viewer/run +0 -48
- package/services/kortix-master/run +0 -16
- package/services/lss-sync/run +0 -22
- package/services/opencode-serve/run +0 -25
- package/services/opencode-web/run +0 -21
package/config/customize.sh
CHANGED
|
@@ -14,130 +14,117 @@ if [ -f "$MARKER" ]; then
|
|
|
14
14
|
exit 0
|
|
15
15
|
fi
|
|
16
16
|
|
|
17
|
-
echo "[heyagi] Applying desktop customization..."
|
|
18
|
-
mkdir -p "$CONFIG_DIR/.config/autostart"
|
|
19
|
-
mkdir -p "$CONFIG_DIR/.local/share/konsole"
|
|
17
|
+
echo "[heyagi] Applying XFCE desktop customization (Alpine)..."
|
|
20
18
|
|
|
21
19
|
# ── Symlink presentations into Desktop for easy access ─────────────────────
|
|
22
20
|
mkdir -p "$CONFIG_DIR/presentations"
|
|
23
|
-
# Create a Desktop directory for KDE and symlink presentations into it
|
|
24
21
|
mkdir -p "$CONFIG_DIR/Desktop"
|
|
25
22
|
ln -sfn "$CONFIG_DIR/presentations" "$CONFIG_DIR/Desktop/presentations"
|
|
26
23
|
|
|
27
|
-
# ──
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
# ── XFCE: Wallpaper ───────────────────────────────────────────────────────
|
|
25
|
+
mkdir -p "$CONFIG_DIR/.config/xfce4/xfconf/xfce-perchannel-xml"
|
|
26
|
+
cat > "$CONFIG_DIR/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml" << 'EOF'
|
|
27
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
28
|
+
<channel name="xfce4-desktop" version="1.0">
|
|
29
|
+
<property name="backdrop" type="empty">
|
|
30
|
+
<property name="screen0" type="empty">
|
|
31
|
+
<property name="monitorVNC-0" type="empty">
|
|
32
|
+
<property name="workspace0" type="empty">
|
|
33
|
+
<property name="last-image" type="string" value="/usr/share/wallpapers/heyagi/wallpaper.png"/>
|
|
34
|
+
<property name="image-style" type="int" value="5"/>
|
|
35
|
+
<property name="color-style" type="int" value="0"/>
|
|
36
|
+
<property name="rgba1" type="array">
|
|
37
|
+
<value type="double" value="0.10196"/>
|
|
38
|
+
<value type="double" value="0.10588"/>
|
|
39
|
+
<value type="double" value="0.14902"/>
|
|
40
|
+
<value type="double" value="1.0"/>
|
|
41
|
+
</property>
|
|
42
|
+
</property>
|
|
43
|
+
</property>
|
|
44
|
+
<property name="monitorscreen" type="empty">
|
|
45
|
+
<property name="workspace0" type="empty">
|
|
46
|
+
<property name="last-image" type="string" value="/usr/share/wallpapers/heyagi/wallpaper.png"/>
|
|
47
|
+
<property name="image-style" type="int" value="5"/>
|
|
48
|
+
<property name="color-style" type="int" value="0"/>
|
|
49
|
+
<property name="rgba1" type="array">
|
|
50
|
+
<value type="double" value="0.10196"/>
|
|
51
|
+
<value type="double" value="0.10588"/>
|
|
52
|
+
<value type="double" value="0.14902"/>
|
|
53
|
+
<value type="double" value="1.0"/>
|
|
54
|
+
</property>
|
|
55
|
+
</property>
|
|
56
|
+
</property>
|
|
57
|
+
</property>
|
|
58
|
+
</property>
|
|
59
|
+
</channel>
|
|
40
60
|
EOF
|
|
41
61
|
|
|
42
|
-
# ──
|
|
43
|
-
cat > "$CONFIG_DIR/.config/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
# ── XFCE: Dark theme (adw-gtk3-dark — Alpine's equivalent of Adwaita-dark)
|
|
63
|
+
cat > "$CONFIG_DIR/.config/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml" << 'EOF'
|
|
64
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
65
|
+
<channel name="xsettings" version="1.0">
|
|
66
|
+
<property name="Net" type="empty">
|
|
67
|
+
<property name="ThemeName" type="string" value="adw-gtk3-dark"/>
|
|
68
|
+
<property name="IconThemeName" type="string" value="Adwaita"/>
|
|
69
|
+
<property name="CursorThemeName" type="string" value="Breeze_Light"/>
|
|
70
|
+
</property>
|
|
71
|
+
<property name="Gtk" type="empty">
|
|
72
|
+
<property name="FontName" type="string" value="Sans 10"/>
|
|
73
|
+
<property name="CursorThemeSize" type="int" value="24"/>
|
|
74
|
+
</property>
|
|
75
|
+
</channel>
|
|
54
76
|
EOF
|
|
55
77
|
|
|
56
|
-
# ──
|
|
57
|
-
cat > "$CONFIG_DIR/.config/
|
|
58
|
-
|
|
59
|
-
name=
|
|
78
|
+
# ── XFCE: Window Manager dark theme (Daloa — only xfwm4 theme on Alpine)
|
|
79
|
+
cat > "$CONFIG_DIR/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml" << 'EOF'
|
|
80
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
81
|
+
<channel name="xfwm4" version="1.0">
|
|
82
|
+
<property name="general" type="empty">
|
|
83
|
+
<property name="theme" type="string" value="Daloa"/>
|
|
84
|
+
<property name="title_font" type="string" value="Sans Bold 9"/>
|
|
85
|
+
<property name="placement_ratio" type="int" value="50"/>
|
|
86
|
+
<property name="cycle_tabwin_mode" type="int" value="0"/>
|
|
87
|
+
</property>
|
|
88
|
+
</channel>
|
|
60
89
|
EOF
|
|
61
90
|
|
|
62
|
-
# ──
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
91
|
+
# ── XFCE: Terminal dark profile ──────────────────────────────────────────
|
|
92
|
+
mkdir -p "$CONFIG_DIR/.config/xfce4/terminal"
|
|
93
|
+
cat > "$CONFIG_DIR/.config/xfce4/terminal/terminalrc" << 'EOF'
|
|
94
|
+
[Configuration]
|
|
95
|
+
BackgroundMode=TERMINAL_BACKGROUND_TRANSPARENT
|
|
96
|
+
BackgroundDarkness=0.90
|
|
97
|
+
ColorForeground=#c0caf5
|
|
98
|
+
ColorBackground=#1a1b26
|
|
99
|
+
ColorCursor=#c0caf5
|
|
100
|
+
ColorPalette=#15161e;#f7768e;#9ece6a;#e0af68;#7aa2f7;#bb9af7;#7dcfff;#a9b1d6;#414868;#f7768e;#9ece6a;#e0af68;#7aa2f7;#bb9af7;#7dcfff;#c0caf5
|
|
101
|
+
FontName=Monospace 11
|
|
102
|
+
MiscAlwaysShowTabs=FALSE
|
|
103
|
+
MiscBordersDefault=TRUE
|
|
104
|
+
MiscShowUnsafePasteDialog=FALSE
|
|
105
|
+
ScrollingUnlimited=TRUE
|
|
74
106
|
EOF
|
|
75
107
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
ToolBarsMovable=Disabled
|
|
108
|
+
# ── GTK dark theme (fallback for GTK2 apps) ───────────────────────────────
|
|
109
|
+
cat > "$CONFIG_DIR/.gtkrc-2.0" << 'EOF'
|
|
110
|
+
gtk-theme-name="adw-gtk3-dark"
|
|
111
|
+
gtk-icon-theme-name="Adwaita"
|
|
112
|
+
gtk-font-name="Sans 10"
|
|
113
|
+
gtk-cursor-theme-name="Breeze_Light"
|
|
83
114
|
EOF
|
|
84
115
|
|
|
85
|
-
|
|
86
|
-
cat > "$CONFIG_DIR/.config/
|
|
87
|
-
[
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
116
|
+
mkdir -p "$CONFIG_DIR/.config/gtk-3.0"
|
|
117
|
+
cat > "$CONFIG_DIR/.config/gtk-3.0/settings.ini" << 'EOF'
|
|
118
|
+
[Settings]
|
|
119
|
+
gtk-theme-name=adw-gtk3-dark
|
|
120
|
+
gtk-icon-theme-name=Adwaita
|
|
121
|
+
gtk-font-name=Sans 10
|
|
122
|
+
gtk-application-prefer-dark-theme=true
|
|
123
|
+
gtk-cursor-theme-name=Breeze_Light
|
|
92
124
|
EOF
|
|
93
125
|
|
|
94
|
-
cat > /usr/share/wallpapers/heyagi/apply-desktop.sh << 'SCRIPT'
|
|
95
|
-
#!/bin/bash
|
|
96
|
-
sleep 5
|
|
97
|
-
|
|
98
|
-
plasma-apply-wallpaperimage /usr/share/wallpapers/heyagi/wallpaper.png
|
|
99
|
-
|
|
100
|
-
PLASMA_RC="$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc"
|
|
101
|
-
ICON_PATH="/usr/share/icons/heyagi/kortix-symbol-white.svg"
|
|
102
|
-
|
|
103
|
-
if [ -f "$PLASMA_RC" ]; then
|
|
104
|
-
# Find the kickoff applet's [Configuration][General] section and inject icon
|
|
105
|
-
# Get the containment/applet IDs for kickoff
|
|
106
|
-
KICKOFF_SECTION=$(grep -B3 "plugin=org.kde.plasma.kickoff" "$PLASMA_RC" | grep "^\[Containments\]" | tail -1)
|
|
107
|
-
|
|
108
|
-
if [ -n "$KICKOFF_SECTION" ]; then
|
|
109
|
-
# Build the [Configuration][General] section name
|
|
110
|
-
GENERAL_SECTION="${KICKOFF_SECTION%]}][Configuration][General]"
|
|
111
|
-
|
|
112
|
-
if grep -q "$(echo "$GENERAL_SECTION" | sed 's/\[/\\[/g; s/\]/\\]/g')" "$PLASMA_RC"; then
|
|
113
|
-
# Section exists -- replace or add icon line
|
|
114
|
-
ESCAPED=$(echo "$GENERAL_SECTION" | sed 's/\[/\\[/g; s/\]/\\]/g')
|
|
115
|
-
if grep -A10 "$ESCAPED" "$PLASMA_RC" | grep -q "^icon="; then
|
|
116
|
-
sed -i "/$ESCAPED/,/^\[/{s|^icon=.*|icon=$ICON_PATH|}" "$PLASMA_RC"
|
|
117
|
-
else
|
|
118
|
-
sed -i "/$ESCAPED/a icon=$ICON_PATH" "$PLASMA_RC"
|
|
119
|
-
fi
|
|
120
|
-
else
|
|
121
|
-
# Section doesn't exist -- create it
|
|
122
|
-
CONF_SECTION="${KICKOFF_SECTION%]}][Configuration]"
|
|
123
|
-
ESCAPED_CONF=$(echo "$CONF_SECTION" | sed 's/\[/\\[/g; s/\]/\\]/g')
|
|
124
|
-
sed -i "/$ESCAPED_CONF/,/^\[/{/^\[.*\]/!b;i\\${GENERAL_SECTION}\nicon=$ICON_PATH
|
|
125
|
-
}" "$PLASMA_RC"
|
|
126
|
-
fi
|
|
127
|
-
fi
|
|
128
|
-
|
|
129
|
-
# Restart plasmashell to pick up icon change
|
|
130
|
-
kquitapp5 plasmashell 2>/dev/null
|
|
131
|
-
sleep 2
|
|
132
|
-
kstart5 plasmashell 2>/dev/null &
|
|
133
|
-
fi
|
|
134
|
-
SCRIPT
|
|
135
|
-
chmod +x /usr/share/wallpapers/heyagi/apply-desktop.sh
|
|
136
|
-
|
|
137
126
|
# ── Fix ownership ──────────────────────────────────────────────────────────
|
|
138
|
-
# Give abc full ownership of everything under /workspace so opencode and its
|
|
139
|
-
# agents can freely create directories and files (presentations, output, etc.)
|
|
140
127
|
chown -R abc:abc "$CONFIG_DIR" 2>/dev/null
|
|
141
128
|
|
|
142
129
|
touch "$MARKER"
|
|
143
|
-
echo "[heyagi]
|
|
130
|
+
echo "[heyagi] XFCE customization complete."
|
|
@@ -12,11 +12,11 @@ if [ "$ENV_MODE" = "cloud" ] || [ "$ENV_MODE" = "production" ]; then
|
|
|
12
12
|
echo "[Kortix] Services will still start; set KORTIX_API_URL later to enable model routing"
|
|
13
13
|
else
|
|
14
14
|
# Write env overrides that s6 services will inherit via with-contenv
|
|
15
|
-
printf '%s' "${KORTIX_API_URL}/tavily" > /
|
|
16
|
-
printf '%s' "${KORTIX_API_URL}/serper" > /
|
|
17
|
-
printf '%s' "${KORTIX_API_URL}/firecrawl" > /
|
|
18
|
-
printf '%s' "${KORTIX_API_URL}/replicate" > /
|
|
19
|
-
printf '%s' "${KORTIX_API_URL}/context7" > /
|
|
15
|
+
printf '%s' "${KORTIX_API_URL}/tavily" > /run/s6/container_environment/TAVILY_API_URL
|
|
16
|
+
printf '%s' "${KORTIX_API_URL}/serper" > /run/s6/container_environment/SERPER_API_URL
|
|
17
|
+
printf '%s' "${KORTIX_API_URL}/firecrawl" > /run/s6/container_environment/FIRECRAWL_API_URL
|
|
18
|
+
printf '%s' "${KORTIX_API_URL}/replicate" > /run/s6/container_environment/REPLICATE_API_URL
|
|
19
|
+
printf '%s' "${KORTIX_API_URL}/context7" > /run/s6/container_environment/CONTEXT7_API_URL
|
|
20
20
|
|
|
21
21
|
echo "[Kortix] SDK URLs routed through ${KORTIX_API_URL}"
|
|
22
22
|
fi
|
|
@@ -18,8 +18,18 @@ await secretStore.loadIntoProcessEnv()
|
|
|
18
18
|
app.use('*', logger())
|
|
19
19
|
app.use('*', cors())
|
|
20
20
|
|
|
21
|
-
// Health check
|
|
22
|
-
app.get('/kortix/health', (c) =>
|
|
21
|
+
// Health check — includes current sandbox version
|
|
22
|
+
app.get('/kortix/health', async (c) => {
|
|
23
|
+
let version = '0.0.0'
|
|
24
|
+
try {
|
|
25
|
+
const file = Bun.file('/opt/kortix/.version')
|
|
26
|
+
if (await file.exists()) {
|
|
27
|
+
const data = await file.json()
|
|
28
|
+
version = data.version || '0.0.0'
|
|
29
|
+
}
|
|
30
|
+
} catch {}
|
|
31
|
+
return c.json({ status: 'ok', version })
|
|
32
|
+
})
|
|
23
33
|
|
|
24
34
|
// Update check — /kortix/update and /kortix/update/status
|
|
25
35
|
app.route('/kortix/update', updateRouter)
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import { config } from '../config';
|
|
3
|
-
|
|
4
|
-
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
5
|
-
|
|
6
|
-
interface LocalVersion {
|
|
7
|
-
version: string;
|
|
8
|
-
updatedAt: string;
|
|
9
|
-
}
|
|
10
2
|
|
|
11
3
|
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
12
4
|
|
|
@@ -32,35 +24,17 @@ let updateInProgress = false;
|
|
|
32
24
|
|
|
33
25
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
34
26
|
|
|
35
|
-
async function readLocalVersion(): Promise<
|
|
27
|
+
async function readLocalVersion(): Promise<string> {
|
|
36
28
|
try {
|
|
37
29
|
const file = Bun.file(VERSION_FILE);
|
|
38
30
|
if (await file.exists()) {
|
|
39
|
-
|
|
31
|
+
const data = await file.json();
|
|
32
|
+
return data.version || '0.0.0';
|
|
40
33
|
}
|
|
41
34
|
} catch (e) {
|
|
42
35
|
console.error('[Update] Failed to read version file:', e);
|
|
43
36
|
}
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function fetchLatestVersion(): Promise<string | null> {
|
|
48
|
-
const url = `${config.KORTIX_API_URL}/v1/sandbox/version`;
|
|
49
|
-
try {
|
|
50
|
-
const res = await fetch(url, {
|
|
51
|
-
headers: { 'Accept': 'application/json' },
|
|
52
|
-
signal: AbortSignal.timeout(10_000),
|
|
53
|
-
});
|
|
54
|
-
if (!res.ok) {
|
|
55
|
-
console.error(`[Update] Version fetch failed: ${res.status}`);
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const data = await res.json() as { version: string };
|
|
59
|
-
return data.version;
|
|
60
|
-
} catch (e) {
|
|
61
|
-
console.error('[Update] Failed to fetch version:', e);
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
37
|
+
return '0.0.0';
|
|
64
38
|
}
|
|
65
39
|
|
|
66
40
|
async function run(cmd: string): Promise<{ ok: boolean; output: string }> {
|
|
@@ -116,62 +90,45 @@ async function performUpdate(targetVersion: string): Promise<{
|
|
|
116
90
|
|
|
117
91
|
const updateRouter = new Hono();
|
|
118
92
|
|
|
119
|
-
/**
|
|
120
|
-
* GET /kortix/update/status
|
|
121
|
-
*
|
|
122
|
-
* Returns current sandbox version + latest available version.
|
|
123
|
-
* Frontend uses this to decide whether to show "Update available".
|
|
124
|
-
* Read-only — does NOT trigger any update.
|
|
125
|
-
*/
|
|
126
|
-
updateRouter.get('/status', async (c) => {
|
|
127
|
-
const local = await readLocalVersion();
|
|
128
|
-
const latest = await fetchLatestVersion();
|
|
129
|
-
|
|
130
|
-
return c.json({
|
|
131
|
-
currentVersion: local.version,
|
|
132
|
-
latestVersion: latest || 'unknown',
|
|
133
|
-
updateAvailable: latest ? local.version !== latest : false,
|
|
134
|
-
updatedAt: local.updatedAt,
|
|
135
|
-
updateInProgress,
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
93
|
/**
|
|
140
94
|
* POST /kortix/update
|
|
141
95
|
*
|
|
142
|
-
* User-triggered update.
|
|
143
|
-
*
|
|
96
|
+
* User-triggered update. Frontend passes the target version.
|
|
97
|
+
* Installs the package, restarts services.
|
|
98
|
+
* Only runs when explicitly called.
|
|
99
|
+
*
|
|
100
|
+
* Body: { "version": "0.4.3" }
|
|
144
101
|
*/
|
|
145
102
|
updateRouter.post('/', async (c) => {
|
|
146
103
|
if (updateInProgress) {
|
|
147
104
|
return c.json({ error: 'Update already in progress' }, 409);
|
|
148
105
|
}
|
|
149
106
|
|
|
107
|
+
const body = await c.req.json().catch(() => ({}));
|
|
108
|
+
const targetVersion = body.version;
|
|
109
|
+
|
|
110
|
+
if (!targetVersion || typeof targetVersion !== 'string') {
|
|
111
|
+
return c.json({ error: 'Missing "version" in request body' }, 400);
|
|
112
|
+
}
|
|
113
|
+
|
|
150
114
|
updateInProgress = true;
|
|
151
115
|
try {
|
|
152
|
-
const
|
|
153
|
-
const latestVersion = await fetchLatestVersion();
|
|
154
|
-
|
|
155
|
-
if (!latestVersion) {
|
|
156
|
-
return c.json({ error: 'Could not reach version service' }, 502);
|
|
157
|
-
}
|
|
116
|
+
const currentVersion = await readLocalVersion();
|
|
158
117
|
|
|
159
|
-
if (
|
|
118
|
+
if (currentVersion === targetVersion) {
|
|
160
119
|
return c.json({
|
|
161
120
|
upToDate: true,
|
|
162
|
-
currentVersion
|
|
163
|
-
latestVersion,
|
|
121
|
+
currentVersion,
|
|
164
122
|
});
|
|
165
123
|
}
|
|
166
124
|
|
|
167
|
-
console.log(`[Update] User triggered: ${
|
|
168
|
-
const update = await performUpdate(
|
|
125
|
+
console.log(`[Update] User triggered: ${currentVersion} -> ${targetVersion}`);
|
|
126
|
+
const update = await performUpdate(targetVersion);
|
|
169
127
|
|
|
170
128
|
return c.json({
|
|
171
129
|
success: update.success,
|
|
172
|
-
previousVersion:
|
|
173
|
-
currentVersion: update.success ?
|
|
174
|
-
latestVersion,
|
|
130
|
+
previousVersion: currentVersion,
|
|
131
|
+
currentVersion: update.success ? targetVersion : currentVersion,
|
|
175
132
|
output: update.output,
|
|
176
133
|
});
|
|
177
134
|
} catch (e) {
|
|
@@ -9,8 +9,8 @@ The Kortix Cron service runs outside the sandbox as a platform service. It manag
|
|
|
9
9
|
|
|
10
10
|
## Architecture
|
|
11
11
|
|
|
12
|
-
- **Service**: `kortix-
|
|
13
|
-
- **Database**: `
|
|
12
|
+
- **Service**: `kortix-api` (Bun + Hono) running at port 8008
|
|
13
|
+
- **Database**: `kortix` schema in Supabase PostgreSQL (Drizzle ORM)
|
|
14
14
|
- **Scheduler**: Polling loop (1s tick) that checks for due triggers
|
|
15
15
|
- **Executor**: Calls OpenCode API inside sandbox to create sessions and send prompts
|
|
16
16
|
|
|
@@ -44,7 +44,7 @@ The Kortix Cron service runs outside the sandbox as a platform service. It manag
|
|
|
44
44
|
|
|
45
45
|
## API Reference
|
|
46
46
|
|
|
47
|
-
Base URL: `http://localhost:
|
|
47
|
+
Base URL: `http://localhost:8008` (local) or the deployed service URL.
|
|
48
48
|
|
|
49
49
|
All `/v1/*` endpoints require `Authorization: Bearer <supabase-jwt>`.
|
|
50
50
|
|
|
@@ -52,7 +52,7 @@ All `/v1/*` endpoints require `Authorization: Bearer <supabase-jwt>`.
|
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
54
|
# Register a sandbox
|
|
55
|
-
curl -X POST http://localhost:
|
|
55
|
+
curl -X POST http://localhost:8008/v1/sandboxes \
|
|
56
56
|
-H "Authorization: Bearer $TOKEN" \
|
|
57
57
|
-H "Content-Type: application/json" \
|
|
58
58
|
-d '{
|
|
@@ -62,11 +62,11 @@ curl -X POST http://localhost:8011/v1/sandboxes \
|
|
|
62
62
|
}'
|
|
63
63
|
|
|
64
64
|
# List sandboxes
|
|
65
|
-
curl http://localhost:
|
|
65
|
+
curl http://localhost:8008/v1/sandboxes \
|
|
66
66
|
-H "Authorization: Bearer $TOKEN"
|
|
67
67
|
|
|
68
68
|
# Check sandbox health
|
|
69
|
-
curl -X POST http://localhost:
|
|
69
|
+
curl -X POST http://localhost:8008/v1/sandboxes/{id}/health \
|
|
70
70
|
-H "Authorization: Bearer $TOKEN"
|
|
71
71
|
```
|
|
72
72
|
|
|
@@ -74,7 +74,7 @@ curl -X POST http://localhost:8011/v1/sandboxes/{id}/health \
|
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
76
|
# Create a trigger - daily report at 9 AM UTC
|
|
77
|
-
curl -X POST http://localhost:
|
|
77
|
+
curl -X POST http://localhost:8008/v1/triggers \
|
|
78
78
|
-H "Authorization: Bearer $TOKEN" \
|
|
79
79
|
-H "Content-Type: application/json" \
|
|
80
80
|
-d '{
|
|
@@ -88,7 +88,7 @@ curl -X POST http://localhost:8011/v1/triggers \
|
|
|
88
88
|
}'
|
|
89
89
|
|
|
90
90
|
# Create a trigger - every 5 minutes health check
|
|
91
|
-
curl -X POST http://localhost:
|
|
91
|
+
curl -X POST http://localhost:8008/v1/triggers \
|
|
92
92
|
-H "Authorization: Bearer $TOKEN" \
|
|
93
93
|
-H "Content-Type: application/json" \
|
|
94
94
|
-d '{
|
|
@@ -101,23 +101,23 @@ curl -X POST http://localhost:8011/v1/triggers \
|
|
|
101
101
|
}'
|
|
102
102
|
|
|
103
103
|
# List triggers
|
|
104
|
-
curl http://localhost:
|
|
104
|
+
curl http://localhost:8008/v1/triggers \
|
|
105
105
|
-H "Authorization: Bearer $TOKEN"
|
|
106
106
|
|
|
107
107
|
# Pause a trigger
|
|
108
|
-
curl -X POST http://localhost:
|
|
108
|
+
curl -X POST http://localhost:8008/v1/triggers/{id}/pause \
|
|
109
109
|
-H "Authorization: Bearer $TOKEN"
|
|
110
110
|
|
|
111
111
|
# Resume a trigger
|
|
112
|
-
curl -X POST http://localhost:
|
|
112
|
+
curl -X POST http://localhost:8008/v1/triggers/{id}/resume \
|
|
113
113
|
-H "Authorization: Bearer $TOKEN"
|
|
114
114
|
|
|
115
115
|
# Fire a trigger immediately (manual run)
|
|
116
|
-
curl -X POST http://localhost:
|
|
116
|
+
curl -X POST http://localhost:8008/v1/triggers/{id}/run \
|
|
117
117
|
-H "Authorization: Bearer $TOKEN"
|
|
118
118
|
|
|
119
119
|
# Delete a trigger
|
|
120
|
-
curl -X DELETE http://localhost:
|
|
120
|
+
curl -X DELETE http://localhost:8008/v1/triggers/{id} \
|
|
121
121
|
-H "Authorization: Bearer $TOKEN"
|
|
122
122
|
```
|
|
123
123
|
|
|
@@ -125,30 +125,30 @@ curl -X DELETE http://localhost:8011/v1/triggers/{id} \
|
|
|
125
125
|
|
|
126
126
|
```bash
|
|
127
127
|
# List all executions
|
|
128
|
-
curl "http://localhost:
|
|
128
|
+
curl "http://localhost:8008/v1/executions?limit=20" \
|
|
129
129
|
-H "Authorization: Bearer $TOKEN"
|
|
130
130
|
|
|
131
131
|
# Filter by status
|
|
132
|
-
curl "http://localhost:
|
|
132
|
+
curl "http://localhost:8008/v1/executions?status=failed" \
|
|
133
133
|
-H "Authorization: Bearer $TOKEN"
|
|
134
134
|
|
|
135
135
|
# Filter by date range
|
|
136
|
-
curl "http://localhost:
|
|
136
|
+
curl "http://localhost:8008/v1/executions?since=2026-02-01T00:00:00Z&until=2026-02-11T00:00:00Z" \
|
|
137
137
|
-H "Authorization: Bearer $TOKEN"
|
|
138
138
|
|
|
139
139
|
# Executions for a specific trigger
|
|
140
|
-
curl http://localhost:
|
|
140
|
+
curl http://localhost:8008/v1/executions/by-trigger/{triggerId} \
|
|
141
141
|
-H "Authorization: Bearer $TOKEN"
|
|
142
142
|
|
|
143
143
|
# Get execution details
|
|
144
|
-
curl http://localhost:
|
|
144
|
+
curl http://localhost:8008/v1/executions/{id} \
|
|
145
145
|
-H "Authorization: Bearer $TOKEN"
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
### Health Check (no auth)
|
|
149
149
|
|
|
150
150
|
```bash
|
|
151
|
-
curl http://localhost:
|
|
151
|
+
curl http://localhost:8008/health
|
|
152
152
|
# Returns: { status, service, timestamp, scheduler: { running, tickCount, lastTick } }
|
|
153
153
|
```
|
|
154
154
|
|