oysterun 1.5.4 → 1.5.6
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/dev/client/web/index.html +217 -58
- package/docs/routec/skill_installation.md +35 -0
- package/host-service/assets/product-skills/Oysterun/SKILL.md +9 -0
- package/host-service/assets/product-skills/Oysterun/modules/oysterun-scheduler/SKILL.md +38 -11
- package/host-service/assets/product-skills/oysterun-scheduler/SKILL.md +38 -11
- package/host-service/browser-root-project-index.mjs +127 -1
- package/host-service/package.json +2 -2
- package/host-service/portable-scheduler-definitions.mjs +160 -35
- package/host-service/scheduler-service.mjs +16 -0
- package/host-service/server.mjs +159 -74
- package/host-service/session-manager.mjs +1 -0
- package/package.json +1 -1
|
@@ -8659,6 +8659,13 @@
|
|
|
8659
8659
|
data-session-setup-web-shared="web.enabled"
|
|
8660
8660
|
/>
|
|
8661
8661
|
</label>
|
|
8662
|
+
<div
|
|
8663
|
+
id="create-website-authority-hint"
|
|
8664
|
+
class="field-hint field-warning"
|
|
8665
|
+
>
|
|
8666
|
+
Website is available only for agents in the Browser
|
|
8667
|
+
Root.
|
|
8668
|
+
</div>
|
|
8662
8669
|
</div>
|
|
8663
8670
|
<label
|
|
8664
8671
|
class="kv-label"
|
|
@@ -13325,6 +13332,12 @@ Waiting for Claude login output…</pre
|
|
|
13325
13332
|
let lastCreateStartActivationAt = 0;
|
|
13326
13333
|
let createFormPreferenceVersion = 0;
|
|
13327
13334
|
let latestCreateFolderConfigRequestId = 0;
|
|
13335
|
+
let createWebsiteAuthorityState = {
|
|
13336
|
+
folderPath: "",
|
|
13337
|
+
projectAgentId: "",
|
|
13338
|
+
eligible: false,
|
|
13339
|
+
reason: "Website is available only for agents in the Browser Root.",
|
|
13340
|
+
};
|
|
13328
13341
|
let createFormDraftRouteKey = "";
|
|
13329
13342
|
let createSubmitState = {
|
|
13330
13343
|
inFlight: false,
|
|
@@ -26803,6 +26816,7 @@ Waiting for Claude login output…</pre
|
|
|
26803
26816
|
function renderAgentProfileWebsiteAccessRow(liveSession) {
|
|
26804
26817
|
syncAgentProfileWebsiteAccessSession(liveSession);
|
|
26805
26818
|
const website = getLiveSessionWebsite(liveSession);
|
|
26819
|
+
const websiteAuthorized = website?.browser_root_authorized === true;
|
|
26806
26820
|
const enabled = website?.enabled === true;
|
|
26807
26821
|
const access = normalizeAgentWebAccess(website?.access);
|
|
26808
26822
|
const websitePassword = getOwnerVisibleWebsitePassword(website);
|
|
@@ -26836,16 +26850,27 @@ Waiting for Claude login output…</pre
|
|
|
26836
26850
|
type="checkbox"
|
|
26837
26851
|
data-session-profile-web-enabled="web.enabled"
|
|
26838
26852
|
${enabled ? "checked" : ""}
|
|
26839
|
-
${saving ? "disabled" : ""}
|
|
26853
|
+
${saving || !websiteAuthorized ? "disabled" : ""}
|
|
26840
26854
|
/>
|
|
26841
26855
|
</label>
|
|
26856
|
+
${
|
|
26857
|
+
websiteAuthorized
|
|
26858
|
+
? ""
|
|
26859
|
+
: `<div
|
|
26860
|
+
class="field-hint field-warning"
|
|
26861
|
+
data-session-profile-website-authority="outside_browser_root"
|
|
26862
|
+
>${esc(
|
|
26863
|
+
website?.reason_message ||
|
|
26864
|
+
"Website is available only for agents in the Browser Root."
|
|
26865
|
+
)}</div>`
|
|
26866
|
+
}
|
|
26842
26867
|
<label class="field compact-field" for="agent-profile-website-access">
|
|
26843
26868
|
<span>Access</span>
|
|
26844
26869
|
<select
|
|
26845
26870
|
id="agent-profile-website-access"
|
|
26846
26871
|
data-session-profile-web-access="web.access"
|
|
26847
26872
|
onchange="window.syncAgentProfileWebsitePasswordMode && window.syncAgentProfileWebsitePasswordMode()"
|
|
26848
|
-
${saving ? "disabled" : ""}
|
|
26873
|
+
${saving || !websiteAuthorized ? "disabled" : ""}
|
|
26849
26874
|
>${renderAgentWebAccessOptions(access)}</select>
|
|
26850
26875
|
</label>
|
|
26851
26876
|
<label
|
|
@@ -26863,7 +26888,11 @@ Waiting for Claude login output…</pre
|
|
|
26863
26888
|
value="${esc(websitePassword)}"
|
|
26864
26889
|
data-session-profile-web-local="web.password"
|
|
26865
26890
|
oninput="window.syncAgentProfileWebsitePasswordMode && window.syncAgentProfileWebsitePasswordMode()"
|
|
26866
|
-
${
|
|
26891
|
+
${
|
|
26892
|
+
access === "password" && !saving && websiteAuthorized
|
|
26893
|
+
? ""
|
|
26894
|
+
: "disabled"
|
|
26895
|
+
}
|
|
26867
26896
|
/>
|
|
26868
26897
|
<div
|
|
26869
26898
|
id="agent-profile-website-password-status"
|
|
@@ -26895,7 +26924,7 @@ Waiting for Claude login output…</pre
|
|
|
26895
26924
|
data-session-profile-save="website"
|
|
26896
26925
|
data-session-profile-web-access-save="explicit"
|
|
26897
26926
|
onclick="window.saveAgentProfileWebsiteAccess && window.saveAgentProfileWebsiteAccess()"
|
|
26898
|
-
${saving ? "disabled" : ""}
|
|
26927
|
+
${saving || !websiteAuthorized ? "disabled" : ""}
|
|
26899
26928
|
>${saving ? "Saving..." : "Save"}</button>
|
|
26900
26929
|
</div>
|
|
26901
26930
|
${
|
|
@@ -26914,6 +26943,9 @@ Waiting for Claude login output…</pre
|
|
|
26914
26943
|
}
|
|
26915
26944
|
|
|
26916
26945
|
function syncAgentProfileWebsitePasswordMode() {
|
|
26946
|
+
const liveSession = getSelectedLiveSession();
|
|
26947
|
+
const websiteAuthorized =
|
|
26948
|
+
getLiveSessionWebsite(liveSession)?.browser_root_authorized === true;
|
|
26917
26949
|
const access = normalizeAgentWebAccess(
|
|
26918
26950
|
$("agent-profile-website-access")?.value
|
|
26919
26951
|
);
|
|
@@ -26923,13 +26955,12 @@ Waiting for Claude login output…</pre
|
|
|
26923
26955
|
const passwordMode = access === "password";
|
|
26924
26956
|
if (row) row.classList.remove("hidden");
|
|
26925
26957
|
if (input) {
|
|
26926
|
-
input.disabled = !passwordMode;
|
|
26958
|
+
input.disabled = !websiteAuthorized || !passwordMode;
|
|
26927
26959
|
}
|
|
26928
26960
|
if (status) {
|
|
26929
|
-
status.textContent =
|
|
26930
|
-
access,
|
|
26931
|
-
|
|
26932
|
-
);
|
|
26961
|
+
status.textContent = websiteAuthorized
|
|
26962
|
+
? formatOwnerWebsitePasswordHint(access, input?.value || "")
|
|
26963
|
+
: "Website is available only for agents in the Browser Root.";
|
|
26933
26964
|
}
|
|
26934
26965
|
}
|
|
26935
26966
|
|
|
@@ -26938,6 +26969,19 @@ Waiting for Claude login output…</pre
|
|
|
26938
26969
|
if (!liveSession?.sessionId) return;
|
|
26939
26970
|
syncAgentProfileWebsiteAccessSession(liveSession);
|
|
26940
26971
|
if (agentProfileWebsiteAccessState.saving === true) return;
|
|
26972
|
+
const previousWebsite = getLiveSessionWebsite(liveSession);
|
|
26973
|
+
if (previousWebsite?.browser_root_authorized !== true) {
|
|
26974
|
+
agentProfileWebsiteAccessState = {
|
|
26975
|
+
...agentProfileWebsiteAccessState,
|
|
26976
|
+
saving: false,
|
|
26977
|
+
error:
|
|
26978
|
+
previousWebsite?.reason_message ||
|
|
26979
|
+
"Website is available only for agents in the Browser Root.",
|
|
26980
|
+
status: "",
|
|
26981
|
+
};
|
|
26982
|
+
renderAgentProfileView();
|
|
26983
|
+
return;
|
|
26984
|
+
}
|
|
26941
26985
|
const select = $("agent-profile-website-access");
|
|
26942
26986
|
const updateConfig = true;
|
|
26943
26987
|
const nextEnabled =
|
|
@@ -26947,7 +26991,6 @@ Waiting for Claude login output…</pre
|
|
|
26947
26991
|
nextAccess === "password"
|
|
26948
26992
|
? String($("agent-profile-website-password")?.value || "").trim()
|
|
26949
26993
|
: "";
|
|
26950
|
-
const previousWebsite = getLiveSessionWebsite(liveSession);
|
|
26951
26994
|
if (nextAccess === "password" && !nextWebsitePassword) {
|
|
26952
26995
|
agentProfileWebsiteAccessState = {
|
|
26953
26996
|
...agentProfileWebsiteAccessState,
|
|
@@ -37739,6 +37782,59 @@ Waiting for Claude login output…</pre
|
|
|
37739
37782
|
syncCreateAllowedPathsShortcutState();
|
|
37740
37783
|
}
|
|
37741
37784
|
|
|
37785
|
+
function isCreateWebsiteEligible() {
|
|
37786
|
+
return (
|
|
37787
|
+
createWebsiteAuthorityState.eligible === true &&
|
|
37788
|
+
createWebsiteAuthorityState.projectAgentId ===
|
|
37789
|
+
String($("create-agent-id")?.value || "").trim()
|
|
37790
|
+
);
|
|
37791
|
+
}
|
|
37792
|
+
|
|
37793
|
+
function syncCreateWebsiteAuthorityState() {
|
|
37794
|
+
const eligible = isCreateWebsiteEligible();
|
|
37795
|
+
const enabledInput = $("create-website-enabled");
|
|
37796
|
+
const accessSelect = $("create-website-access");
|
|
37797
|
+
const hint = $("create-website-authority-hint");
|
|
37798
|
+
if (enabledInput) {
|
|
37799
|
+
enabledInput.disabled = !eligible;
|
|
37800
|
+
if (!eligible) enabledInput.checked = false;
|
|
37801
|
+
}
|
|
37802
|
+
if (accessSelect) {
|
|
37803
|
+
accessSelect.disabled = !eligible;
|
|
37804
|
+
if (!eligible) accessSelect.value = "owner_only";
|
|
37805
|
+
}
|
|
37806
|
+
if (!eligible) setCreateWebsitePasswordValue("");
|
|
37807
|
+
if (hint) {
|
|
37808
|
+
hint.textContent =
|
|
37809
|
+
createWebsiteAuthorityState.reason ||
|
|
37810
|
+
"Website is available only for agents in the Browser Root.";
|
|
37811
|
+
hint.classList.toggle("hidden", eligible);
|
|
37812
|
+
}
|
|
37813
|
+
syncCreateWebsitePasswordMode();
|
|
37814
|
+
}
|
|
37815
|
+
|
|
37816
|
+
function setCreateWebsiteAuthorityState({
|
|
37817
|
+
folderPath = "",
|
|
37818
|
+
projectAgentId = "",
|
|
37819
|
+
eligible = false,
|
|
37820
|
+
reason = "",
|
|
37821
|
+
} = {}) {
|
|
37822
|
+
createWebsiteAuthorityState = {
|
|
37823
|
+
folderPath: String(folderPath || "").trim(),
|
|
37824
|
+
projectAgentId: String(projectAgentId || "").trim(),
|
|
37825
|
+
eligible: eligible === true,
|
|
37826
|
+
reason:
|
|
37827
|
+
String(reason || "").trim() ||
|
|
37828
|
+
"Website is available only for agents in the Browser Root.",
|
|
37829
|
+
};
|
|
37830
|
+
if (eligible !== true) {
|
|
37831
|
+
setCreateWebsiteEnabledValue(false);
|
|
37832
|
+
setCreateWebsiteAccessValue("owner_only");
|
|
37833
|
+
setCreateWebsitePasswordValue("");
|
|
37834
|
+
}
|
|
37835
|
+
syncCreateWebsiteAuthorityState();
|
|
37836
|
+
}
|
|
37837
|
+
|
|
37742
37838
|
function setCreateWebsiteAccessValue(value) {
|
|
37743
37839
|
const select = $("create-website-access");
|
|
37744
37840
|
if (!select) return;
|
|
@@ -37774,16 +37870,19 @@ Waiting for Claude login output…</pre
|
|
|
37774
37870
|
const row = $("create-website-password-row");
|
|
37775
37871
|
const input = $("create-website-password");
|
|
37776
37872
|
const status = $("create-website-password-status");
|
|
37873
|
+
const eligible = isCreateWebsiteEligible();
|
|
37777
37874
|
const passwordMode = getCreateWebsiteAccessValue() === "password";
|
|
37778
37875
|
if (row) row.classList.remove("hidden");
|
|
37779
37876
|
if (input) {
|
|
37780
|
-
input.disabled = !passwordMode;
|
|
37877
|
+
input.disabled = !eligible || !passwordMode;
|
|
37781
37878
|
}
|
|
37782
37879
|
if (status) {
|
|
37783
|
-
status.textContent =
|
|
37784
|
-
|
|
37785
|
-
|
|
37786
|
-
|
|
37880
|
+
status.textContent = eligible
|
|
37881
|
+
? formatOwnerWebsitePasswordHint(
|
|
37882
|
+
getCreateWebsiteAccessValue(),
|
|
37883
|
+
input?.value || ""
|
|
37884
|
+
)
|
|
37885
|
+
: "Website settings are unavailable outside the Browser Root.";
|
|
37787
37886
|
}
|
|
37788
37887
|
}
|
|
37789
37888
|
|
|
@@ -37889,6 +37988,10 @@ Waiting for Claude login output…</pre
|
|
|
37889
37988
|
syncSessionSetupInterfaceStyleVisibility();
|
|
37890
37989
|
setCreateWebsiteEnabledValue(HOST_DEFAULT_SESSION_DEFAULTS.web.enabled);
|
|
37891
37990
|
setCreateWebsiteAccessValue(HOST_DEFAULT_SESSION_DEFAULTS.web.access);
|
|
37991
|
+
setCreateWebsiteAuthorityState({
|
|
37992
|
+
folderPath: startFolder,
|
|
37993
|
+
eligible: false,
|
|
37994
|
+
});
|
|
37892
37995
|
setCreateNotificationsEnabledValue(
|
|
37893
37996
|
HOST_DEFAULT_SESSION_DEFAULTS.notifications.enabled
|
|
37894
37997
|
);
|
|
@@ -37981,6 +38084,10 @@ Waiting for Claude login output…</pre
|
|
|
37981
38084
|
syncSessionSetupInterfaceStyleVisibility();
|
|
37982
38085
|
setCreateWebsiteEnabledValue(HOST_DEFAULT_SESSION_DEFAULTS.web.enabled);
|
|
37983
38086
|
setCreateWebsiteAccessValue(HOST_DEFAULT_SESSION_DEFAULTS.web.access);
|
|
38087
|
+
setCreateWebsiteAuthorityState({
|
|
38088
|
+
folderPath: record.agent_folder || "",
|
|
38089
|
+
eligible: false,
|
|
38090
|
+
});
|
|
37984
38091
|
setCreateNotificationsEnabledValue(
|
|
37985
38092
|
HOST_DEFAULT_SESSION_DEFAULTS.notifications.enabled
|
|
37986
38093
|
);
|
|
@@ -38389,14 +38496,15 @@ Waiting for Claude login output…</pre
|
|
|
38389
38496
|
if (liveSession?.website && typeof liveSession.website === "object") {
|
|
38390
38497
|
return liveSession.website;
|
|
38391
38498
|
}
|
|
38392
|
-
|
|
38393
|
-
|
|
38394
|
-
|
|
38395
|
-
|
|
38396
|
-
|
|
38397
|
-
|
|
38398
|
-
|
|
38399
|
-
|
|
38499
|
+
return {
|
|
38500
|
+
enabled: false,
|
|
38501
|
+
available: false,
|
|
38502
|
+
access: "owner_only",
|
|
38503
|
+
browser_root_authorized: false,
|
|
38504
|
+
reason: "session_folder_outside_browser_root",
|
|
38505
|
+
reason_message:
|
|
38506
|
+
"Website is available only for agents in the Browser Root.",
|
|
38507
|
+
};
|
|
38400
38508
|
}
|
|
38401
38509
|
|
|
38402
38510
|
function getOwnerVisibleWebsitePassword(website = {}) {
|
|
@@ -40377,7 +40485,6 @@ Waiting for Claude login output…</pre
|
|
|
40377
40485
|
"approval_policy",
|
|
40378
40486
|
"allow_dangerously_skip_permissions",
|
|
40379
40487
|
"dangerous_mode",
|
|
40380
|
-
"web_access",
|
|
40381
40488
|
"notifications_enabled",
|
|
40382
40489
|
"allowed_paths",
|
|
40383
40490
|
"runtime_capabilities",
|
|
@@ -40529,8 +40636,10 @@ Waiting for Claude login output…</pre
|
|
|
40529
40636
|
payload.interface_type || getCreateDefaultInterfaceType()
|
|
40530
40637
|
);
|
|
40531
40638
|
syncSessionSetupInterfaceStyleVisibility();
|
|
40532
|
-
|
|
40533
|
-
|
|
40639
|
+
setCreateWebsiteAuthorityState({
|
|
40640
|
+
folderPath: draft.agentFolder || "",
|
|
40641
|
+
eligible: false,
|
|
40642
|
+
});
|
|
40534
40643
|
setCreateTelegramSettingsValue({});
|
|
40535
40644
|
$("create-allowed-paths").value = normalizeAllowedPathsForForm(
|
|
40536
40645
|
payload.allowed_paths
|
|
@@ -40603,6 +40712,13 @@ Waiting for Claude login output…</pre
|
|
|
40603
40712
|
syncCreateAllowedPathsShortcutState();
|
|
40604
40713
|
refreshCreateStartButtonEnabled();
|
|
40605
40714
|
refreshUpdateSessionNameButton();
|
|
40715
|
+
if (draft.agentFolder) {
|
|
40716
|
+
void loadFolderConfigIntoCreateForm(draft.agentFolder, {
|
|
40717
|
+
fillAgentIdIfEmpty: false,
|
|
40718
|
+
applyFormValues: false,
|
|
40719
|
+
showError: false,
|
|
40720
|
+
});
|
|
40721
|
+
}
|
|
40606
40722
|
}
|
|
40607
40723
|
|
|
40608
40724
|
function readSessionSetupSchedulerDraftForEditor(
|
|
@@ -48648,14 +48764,6 @@ Waiting for Claude login output…</pre
|
|
|
48648
48764
|
const allowedPaths = isAllowedPathDebugUiVisible()
|
|
48649
48765
|
? parseAllowedPathsInput($("create-allowed-paths").value)
|
|
48650
48766
|
: null;
|
|
48651
|
-
const webAccess = getCreateWebsiteAccessValue();
|
|
48652
|
-
const webPassword =
|
|
48653
|
-
webAccess === "password" ? getCreateWebsitePasswordValue() : "";
|
|
48654
|
-
if (webAccess === "password" && !webPassword) {
|
|
48655
|
-
throw new Error(
|
|
48656
|
-
"Website Password is required when Website Access is Password. Switch Website Access away from Password before clearing it."
|
|
48657
|
-
);
|
|
48658
|
-
}
|
|
48659
48767
|
|
|
48660
48768
|
const payload = {
|
|
48661
48769
|
provider: createRuntime,
|
|
@@ -48672,8 +48780,6 @@ Waiting for Claude login output…</pre
|
|
|
48672
48780
|
createRuntime === "codex" ? codexApproval : undefined,
|
|
48673
48781
|
allow_dangerously_skip_permissions: allowDanger,
|
|
48674
48782
|
dangerous_mode: allowDanger,
|
|
48675
|
-
web_enabled: getCreateWebsiteEnabledValue(),
|
|
48676
|
-
web_access: webAccess,
|
|
48677
48783
|
notifications_enabled: getCreateNotificationsEnabledValue(),
|
|
48678
48784
|
install_oysterun_skills: getCreateInstallOysterunSkillsValue(),
|
|
48679
48785
|
...readTelegramFieldsPayload("create"),
|
|
@@ -48692,9 +48798,6 @@ Waiting for Claude login output…</pre
|
|
|
48692
48798
|
) {
|
|
48693
48799
|
payload.confirm_beta_provider_permission_mode = true;
|
|
48694
48800
|
}
|
|
48695
|
-
if (webPassword) {
|
|
48696
|
-
payload.web_password = webPassword;
|
|
48697
|
-
}
|
|
48698
48801
|
validateTelegramEnabledPayloadOrThrow(
|
|
48699
48802
|
payload,
|
|
48700
48803
|
getCreateTelegramConfiguredState()
|
|
@@ -48702,6 +48805,23 @@ Waiting for Claude login output…</pre
|
|
|
48702
48805
|
return payload;
|
|
48703
48806
|
}
|
|
48704
48807
|
|
|
48808
|
+
function buildCreateWebsitePayload() {
|
|
48809
|
+
if (!isCreateWebsiteEligible()) return null;
|
|
48810
|
+
const webAccess = getCreateWebsiteAccessValue();
|
|
48811
|
+
const webPassword =
|
|
48812
|
+
webAccess === "password" ? getCreateWebsitePasswordValue() : "";
|
|
48813
|
+
if (webAccess === "password" && !webPassword) {
|
|
48814
|
+
throw new Error(
|
|
48815
|
+
"Website Password is required when Website Access is Password. Switch Website Access away from Password before clearing it."
|
|
48816
|
+
);
|
|
48817
|
+
}
|
|
48818
|
+
return {
|
|
48819
|
+
web_enabled: getCreateWebsiteEnabledValue(),
|
|
48820
|
+
web_access: webAccess,
|
|
48821
|
+
...(webPassword ? { web_password: webPassword } : {}),
|
|
48822
|
+
};
|
|
48823
|
+
}
|
|
48824
|
+
|
|
48705
48825
|
function readCreateFormRequest() {
|
|
48706
48826
|
const agent_id = $("create-agent-id").value.trim();
|
|
48707
48827
|
const agent_folder = $("create-agent-folder").value.trim();
|
|
@@ -48724,6 +48844,7 @@ Waiting for Claude login output…</pre
|
|
|
48724
48844
|
configToggleChecked
|
|
48725
48845
|
),
|
|
48726
48846
|
sessionPayload: buildCreateSessionPayload(),
|
|
48847
|
+
websitePayload: buildCreateWebsitePayload(),
|
|
48727
48848
|
};
|
|
48728
48849
|
}
|
|
48729
48850
|
|
|
@@ -48754,6 +48875,7 @@ Waiting for Claude login output…</pre
|
|
|
48754
48875
|
persistConfig,
|
|
48755
48876
|
preventConfigCreate,
|
|
48756
48877
|
sessionPayload,
|
|
48878
|
+
websitePayload,
|
|
48757
48879
|
} = request;
|
|
48758
48880
|
const sessionSetupProof = applyCreateSessionSetupProofAttributes(
|
|
48759
48881
|
buildCreateSessionSetupProviderModelPermissionProof(sessionPayload)
|
|
@@ -48791,28 +48913,37 @@ Waiting for Claude login output…</pre
|
|
|
48791
48913
|
|
|
48792
48914
|
const configPersistenceAction =
|
|
48793
48915
|
getCreateConfigPersistenceAction(configToggleMode);
|
|
48794
|
-
|
|
48795
|
-
|
|
48796
|
-
|
|
48797
|
-
|
|
48798
|
-
|
|
48916
|
+
const shouldPersistWebsite = Boolean(websitePayload);
|
|
48917
|
+
let failureStep =
|
|
48918
|
+
shouldPersistConfig || shouldPersistWebsite
|
|
48919
|
+
? `Could not ${configPersistenceAction.toLowerCase()} .oysterun/config.json`
|
|
48920
|
+
: resumeSessionId
|
|
48921
|
+
? "Could not resume session"
|
|
48922
|
+
: "Could not start session";
|
|
48799
48923
|
try {
|
|
48800
|
-
if (shouldPersistConfig) {
|
|
48924
|
+
if (shouldPersistConfig || shouldPersistWebsite) {
|
|
48801
48925
|
await apiWithAuthRetry(
|
|
48802
48926
|
"PUT",
|
|
48803
48927
|
"/agent/config",
|
|
48804
48928
|
{
|
|
48805
48929
|
agent_id,
|
|
48806
48930
|
agent_folder,
|
|
48807
|
-
...
|
|
48808
|
-
|
|
48809
|
-
|
|
48931
|
+
...(shouldPersistConfig
|
|
48932
|
+
? {
|
|
48933
|
+
...sessionPayload,
|
|
48934
|
+
session_setup_provider_model_permission_proof:
|
|
48935
|
+
sessionSetupProof,
|
|
48936
|
+
}
|
|
48937
|
+
: {}),
|
|
48938
|
+
...(websitePayload || {}),
|
|
48810
48939
|
},
|
|
48811
48940
|
{
|
|
48812
48941
|
onRetry: () => {
|
|
48813
48942
|
if (!isCurrentCreateAttempt(attemptId)) return;
|
|
48814
48943
|
setCreateStatus(
|
|
48815
|
-
|
|
48944
|
+
shouldPersistConfig
|
|
48945
|
+
? `${configPersistenceAction} .oysterun/config.json...`
|
|
48946
|
+
: "Updating Website settings...",
|
|
48816
48947
|
"Retrying config save after a brief auth settle."
|
|
48817
48948
|
);
|
|
48818
48949
|
},
|
|
@@ -50190,6 +50321,7 @@ Waiting for Claude login output…</pre
|
|
|
50190
50321
|
const folderPath = String(path || "").trim();
|
|
50191
50322
|
if (!folderPath) {
|
|
50192
50323
|
hideCreateConfigToggle("");
|
|
50324
|
+
setCreateWebsiteAuthorityState();
|
|
50193
50325
|
refreshCreateStartButtonEnabled();
|
|
50194
50326
|
return;
|
|
50195
50327
|
}
|
|
@@ -50207,20 +50339,38 @@ Waiting for Claude login output…</pre
|
|
|
50207
50339
|
)}${providerQuery}`
|
|
50208
50340
|
);
|
|
50209
50341
|
const resolvedFolderPath = data.agent_folder || folderPath;
|
|
50342
|
+
const currentFolderPath = String(
|
|
50343
|
+
$("create-agent-folder").value || ""
|
|
50344
|
+
).trim();
|
|
50345
|
+
if (
|
|
50346
|
+
requestId !== latestCreateFolderConfigRequestId ||
|
|
50347
|
+
currentFolderPath !== folderPath
|
|
50348
|
+
) {
|
|
50349
|
+
return;
|
|
50350
|
+
}
|
|
50351
|
+
setCreateWebsiteAuthorityState({
|
|
50352
|
+
folderPath: resolvedFolderPath,
|
|
50353
|
+
projectAgentId: data.websiteAgentId || "",
|
|
50354
|
+
eligible:
|
|
50355
|
+
data.websiteEligible === true ||
|
|
50356
|
+
data.website?.browser_root_authorized === true,
|
|
50357
|
+
reason:
|
|
50358
|
+
data.website?.reason_message ||
|
|
50359
|
+
"Website is available only for agents in the Browser Root.",
|
|
50360
|
+
});
|
|
50361
|
+
if (opts.applyFormValues === false && isCreateWebsiteEligible()) {
|
|
50362
|
+
setCreateWebsiteEnabledValue(
|
|
50363
|
+
HOST_DEFAULT_SESSION_DEFAULTS.web.enabled
|
|
50364
|
+
);
|
|
50365
|
+
setCreateWebsiteAccessValue(
|
|
50366
|
+
HOST_DEFAULT_SESSION_DEFAULTS.web.access
|
|
50367
|
+
);
|
|
50368
|
+
}
|
|
50210
50369
|
applyCreateConfigToggleMode(
|
|
50211
50370
|
resolvedFolderPath,
|
|
50212
50371
|
data.hasConfig === true
|
|
50213
50372
|
);
|
|
50214
50373
|
if (opts.applyFormValues !== false) {
|
|
50215
|
-
const currentFolderPath = String(
|
|
50216
|
-
$("create-agent-folder").value || ""
|
|
50217
|
-
).trim();
|
|
50218
|
-
if (
|
|
50219
|
-
requestId !== latestCreateFolderConfigRequestId ||
|
|
50220
|
-
currentFolderPath !== folderPath
|
|
50221
|
-
) {
|
|
50222
|
-
return;
|
|
50223
|
-
}
|
|
50224
50374
|
const preferencesUntouched =
|
|
50225
50375
|
createFormPreferenceVersion === requestPreferenceVersion;
|
|
50226
50376
|
$("create-agent-folder").value = resolvedFolderPath;
|
|
@@ -50307,6 +50457,10 @@ Waiting for Claude login output…</pre
|
|
|
50307
50457
|
refreshCreateStartButtonEnabled();
|
|
50308
50458
|
} catch (err) {
|
|
50309
50459
|
hideCreateConfigToggle(folderPath);
|
|
50460
|
+
setCreateWebsiteAuthorityState({
|
|
50461
|
+
folderPath,
|
|
50462
|
+
eligible: false,
|
|
50463
|
+
});
|
|
50310
50464
|
setCreateProviderSkillStatus(null);
|
|
50311
50465
|
setCreateProviderTrustStatus(null);
|
|
50312
50466
|
refreshCreateStartButtonEnabled();
|
|
@@ -50827,6 +50981,10 @@ Waiting for Claude login output…</pre
|
|
|
50827
50981
|
markCreatePreferencesEdited();
|
|
50828
50982
|
syncCreateAllowedPathsShortcutState();
|
|
50829
50983
|
hideCreateConfigToggle($("create-agent-folder").value);
|
|
50984
|
+
setCreateWebsiteAuthorityState({
|
|
50985
|
+
folderPath: $("create-agent-folder").value,
|
|
50986
|
+
eligible: false,
|
|
50987
|
+
});
|
|
50830
50988
|
refreshUpdateSessionNameButton();
|
|
50831
50989
|
void refreshCreateProviderTrustStatus();
|
|
50832
50990
|
refreshCreateStartButtonEnabled();
|
|
@@ -50834,6 +50992,7 @@ Waiting for Claude login output…</pre
|
|
|
50834
50992
|
$("create-agent-id").addEventListener("input", () => {
|
|
50835
50993
|
markCreatePreferencesEdited();
|
|
50836
50994
|
syncCreateSessionNameDefault();
|
|
50995
|
+
syncCreateWebsiteAuthorityState();
|
|
50837
50996
|
void refreshCreateProviderSkillStatus();
|
|
50838
50997
|
void refreshCreateProviderTrustStatus();
|
|
50839
50998
|
refreshCreateStartButtonEnabled();
|
|
@@ -35,6 +35,41 @@ skills/
|
|
|
35
35
|
Those development roots remain mirror/source parity inputs for source-static and
|
|
36
36
|
package verification. They are not an installed runtime precondition.
|
|
37
37
|
|
|
38
|
+
## Canonical Aggregate And Schema
|
|
39
|
+
|
|
40
|
+
The hand-maintained aggregate source is:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
skills/Oysterun/SKILL.md
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The mirror command copies that file to:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
.codex/skills/Oysterun/SKILL.md
|
|
50
|
+
host-service/assets/product-skills/Oysterun/SKILL.md
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The eight module sources remain `skills/oysterun-*/`. Their provider-facing
|
|
54
|
+
module trees, including `skills/Oysterun/modules/`, are generated mirrors.
|
|
55
|
+
|
|
56
|
+
Oysterun-owned aggregate and module `SKILL.md` files require YAML frontmatter
|
|
57
|
+
with a non-empty lowercase hyphen-case `name` and a non-empty `description`.
|
|
58
|
+
The aggregate metadata name is `oysterun`; its uppercase `Oysterun` installation
|
|
59
|
+
folder remains the P88 path contract.
|
|
60
|
+
|
|
61
|
+
Run:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
node tool_scripts/sync_product_skills_to_codex.mjs
|
|
65
|
+
node tool_scripts/check_product_skill_mirrors.mjs
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Sync validates every canonical input before modifying a generated mirror.
|
|
69
|
+
Mirror checks and npm packaging fail when canonical/generated Oysterun skills
|
|
70
|
+
are invalid or stale. This validation is a source/release guard only; Host
|
|
71
|
+
startup and P88 install/update do not reject arbitrary user-owned skills.
|
|
72
|
+
|
|
38
73
|
## Ownership And Copy Rules
|
|
39
74
|
|
|
40
75
|
The aggregate `Oysterun/SKILL.md` must contain:
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oysterun
|
|
3
|
+
description: Use as the aggregate index for Oysterun product skills installed by Host. Route operations to the specific sessions, session-chat, context, scheduler, mail, notifications, website, or Telegram module skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Oysterun
|
|
2
7
|
|
|
3
8
|
<!-- oysterun-skill-set: true -->
|
|
@@ -28,3 +33,7 @@ can insert stable relative paths such as:
|
|
|
28
33
|
|
|
29
34
|
Do not remove the ownership marker above. The Host refuses to overwrite an
|
|
30
35
|
existing `Oysterun` provider skill folder unless this marker is present.
|
|
36
|
+
|
|
37
|
+
After selecting a module, read and follow that module's `SKILL.md`. The
|
|
38
|
+
aggregate is only a discovery and routing index; it does not replace any
|
|
39
|
+
module-specific safety, authorization, confirmation, or command contract.
|
|
@@ -12,24 +12,26 @@ Canonical product skill source lives at `skills/oysterun-scheduler/`. The repo-l
|
|
|
12
12
|
Use this module skill for normal product scheduler operations. It wraps the P86 product CLI contract:
|
|
13
13
|
|
|
14
14
|
```text
|
|
15
|
-
|
|
15
|
+
$OYSTERUN_CLI_BIN scheduler <action> [options]
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
An external repo operator may use the generated helper, which delegates to the
|
|
19
|
+
same CLI surface:
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
22
|
node .codex/skills/Oysterun/modules/oysterun-scheduler/scripts/oysterun_scheduler.mjs list --host http://localhost:2322
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
When Host injects this skill into a live session,
|
|
25
|
+
When Host injects this skill into a live Claude or Codex session, always use:
|
|
25
26
|
|
|
26
27
|
```bash
|
|
27
|
-
|
|
28
|
+
$OYSTERUN_CLI_BIN scheduler list
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
## Commands
|
|
31
32
|
|
|
32
33
|
- `list`
|
|
34
|
+
- `create --prompt <text> --frequency daily --time HH:mm`
|
|
33
35
|
- `create --session-ref <display-name> --prompt <text> --frequency daily --time HH:mm`
|
|
34
36
|
- `get`
|
|
35
37
|
- `update`
|
|
@@ -42,19 +44,40 @@ node .claude/skills/Oysterun/modules/oysterun-scheduler/scripts/oysterun_schedul
|
|
|
42
44
|
|
|
43
45
|
For Host scheduler rows, `create` targets a portable outside-scheduler setup
|
|
44
46
|
snapshot. In a live Host session, omit the target to use the current session's
|
|
45
|
-
saved setup, or pass `--session-ref <display-name>` for another session.
|
|
47
|
+
saved setup, or pass `--session-ref <display-name>` for another session. The
|
|
48
|
+
resolved session agent folder must be a valid, non-conflicting project under
|
|
49
|
+
the Host Default Browse Root. Use
|
|
46
50
|
rule fields such as `--frequency daily --time HH:mm`, `--frequency weekly
|
|
47
51
|
--weekdays monday,wednesday --time HH:mm`, or `--frequency once --run-at
|
|
48
52
|
<ISO time>`. Do not use `--interval` for Host scheduler rows; use `chat loop
|
|
49
53
|
create --interval ...` for in-session loops.
|
|
50
54
|
|
|
55
|
+
## First Scheduler Initialization
|
|
56
|
+
|
|
57
|
+
The Host owns first-file initialization. For a valid Browser Root project with
|
|
58
|
+
no `.oysterun/schedulers.json`, run the normal create command:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
$OYSTERUN_CLI_BIN scheduler create --prompt "..." --frequency daily --time 09:00
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The Host validates Browser Root authority, copies the current session setup,
|
|
65
|
+
and atomically creates the first portable Scheduler file. Do not manually
|
|
66
|
+
create an empty Scheduler JSON file, write Host SQLite rows, or call a
|
|
67
|
+
`/scheduler/*` endpoint to bootstrap the project.
|
|
68
|
+
|
|
69
|
+
If create reports that the folder is not a Browser Root project, select or move
|
|
70
|
+
the project under Default Browse Root and retry. If it reports a project
|
|
71
|
+
collision or invalid portable file, resolve the stated conflict or repair the
|
|
72
|
+
existing file; do not overwrite it with an empty schema.
|
|
73
|
+
|
|
51
74
|
## Scheduler Setup Snapshot Contract
|
|
52
75
|
|
|
53
76
|
When creating or updating a Host scheduler, prefer an existing session config:
|
|
54
77
|
|
|
55
78
|
```bash
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
$OYSTERUN_CLI_BIN scheduler create --prompt "..." --frequency daily --time 09:00
|
|
80
|
+
$OYSTERUN_CLI_BIN scheduler create --session-ref "My Agent Session" --prompt "..." --frequency daily --time 09:00
|
|
58
81
|
```
|
|
59
82
|
|
|
60
83
|
Do not import Host scheduler internals, call `/scheduler/*` endpoints directly,
|
|
@@ -70,9 +93,10 @@ the injected binary:
|
|
|
70
93
|
$OYSTERUN_CLI_BIN mail send --title "Report ready" --html-file data/latest_report.html
|
|
71
94
|
```
|
|
72
95
|
|
|
73
|
-
|
|
74
|
-
only in an environment variable. Do not call Host
|
|
75
|
-
The `.html` file extension is the Mail
|
|
96
|
+
For a durable report, do not send markdown, auto-format, stdin, `--text`,
|
|
97
|
+
`--body`, or raw HTML held only in an environment variable. Do not call Host
|
|
98
|
+
`/mail/*` endpoints directly. The `.html` file extension is the durable Mail
|
|
99
|
+
report contract.
|
|
76
100
|
|
|
77
101
|
If a route explicitly requires an explicit setup snapshot instead of a current
|
|
78
102
|
or saved session, the snapshot must include the full provider runtime proof:
|
|
@@ -99,12 +123,15 @@ the persisted scheduler target is valid.
|
|
|
99
123
|
|
|
100
124
|
Scheduler jobs that need to send Oysterun Mail should use the normal product
|
|
101
125
|
Mail CLI, not a separate scheduler-only Mail stack. Inside a Host-injected
|
|
102
|
-
scheduler/runtime environment,
|
|
126
|
+
scheduler/runtime environment, a short non-report status may use:
|
|
103
127
|
|
|
104
128
|
```bash
|
|
105
129
|
$OYSTERUN_CLI_BIN mail send --title "Digest ready" --text "Daily tracker finished"
|
|
106
130
|
```
|
|
107
131
|
|
|
132
|
+
If the job produced a report, use the durable `.html` plus `--html-file`
|
|
133
|
+
contract above instead of `--text`.
|
|
134
|
+
|
|
108
135
|
The Host injects a scheduler-run scoped `mail:create` capability for Mail send
|
|
109
136
|
only. The CLI preserves `OYSTERUN_SCHEDULE_ID`,
|
|
110
137
|
`OYSTERUN_SCHEDULE_RUN_ID`, and `OYSTERUN_AGENT_ID` as Mail attribution. Do
|