opendevbrowser 0.0.19 → 0.0.21
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 +32 -24
- package/dist/automation/coordinator.d.ts +61 -2
- package/dist/automation/coordinator.d.ts.map +1 -1
- package/dist/browser/browser-manager.d.ts +6 -1
- package/dist/browser/browser-manager.d.ts.map +1 -1
- package/dist/browser/canvas-manager.d.ts +4 -0
- package/dist/browser/canvas-manager.d.ts.map +1 -1
- package/dist/browser/manager-types.d.ts +6 -1
- package/dist/browser/manager-types.d.ts.map +1 -1
- package/dist/browser/ops-browser-manager.d.ts +6 -1
- package/dist/browser/ops-browser-manager.d.ts.map +1 -1
- package/dist/browser/screencast-recorder.d.ts.map +1 -1
- package/dist/browser/session-inspector.d.ts +39 -0
- package/dist/browser/session-inspector.d.ts.map +1 -1
- package/dist/canvas/document-store.d.ts +14 -5
- package/dist/canvas/document-store.d.ts.map +1 -1
- package/dist/canvas/starters/catalog.d.ts.map +1 -1
- package/dist/canvas/types.d.ts +120 -9
- package/dist/canvas/types.d.ts.map +1 -1
- package/dist/challenges/action-loop.d.ts +2 -1
- package/dist/challenges/action-loop.d.ts.map +1 -1
- package/dist/challenges/capture.d.ts +14 -0
- package/dist/challenges/capture.d.ts.map +1 -0
- package/dist/challenges/index.d.ts +3 -1
- package/dist/challenges/index.d.ts.map +1 -1
- package/dist/challenges/inspect-plan.d.ts +40 -0
- package/dist/challenges/inspect-plan.d.ts.map +1 -0
- package/dist/challenges/orchestrator.d.ts.map +1 -1
- package/dist/challenges/types.d.ts +34 -0
- package/dist/challenges/types.d.ts.map +1 -1
- package/dist/{chunk-YBQECXZX.js → chunk-3VA6XR25.js} +3 -3
- package/dist/chunk-3VA6XR25.js.map +1 -0
- package/dist/{chunk-W4IHGDXV.js → chunk-4KVXCXV3.js} +25778 -24279
- package/dist/chunk-4KVXCXV3.js.map +1 -0
- package/dist/{chunk-5FZQJRBQ.js → chunk-ZE2E7ZGH.js} +3013 -1010
- package/dist/chunk-ZE2E7ZGH.js.map +1 -0
- package/dist/cli/commands/challenge-automation-mode.d.ts +3 -0
- package/dist/cli/commands/challenge-automation-mode.d.ts.map +1 -0
- package/dist/cli/commands/inspiredesign.d.ts +25 -0
- package/dist/cli/commands/inspiredesign.d.ts.map +1 -0
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/nav/review-desktop.d.ts +7 -0
- package/dist/cli/commands/nav/review-desktop.d.ts.map +1 -0
- package/dist/cli/commands/nav/review-shared.d.ts +10 -0
- package/dist/cli/commands/nav/review-shared.d.ts.map +1 -0
- package/dist/cli/commands/nav/review.d.ts.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/session/inspector-audit.d.ts +7 -0
- package/dist/cli/commands/session/inspector-audit.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector-plan.d.ts +7 -0
- package/dist/cli/commands/session/inspector-plan.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector-shared.d.ts +11 -0
- package/dist/cli/commands/session/inspector-shared.d.ts.map +1 -0
- package/dist/cli/commands/session/inspector.d.ts +1 -11
- package/dist/cli/commands/session/inspector.d.ts.map +1 -1
- package/dist/cli/commands/status-capabilities.d.ts +7 -0
- package/dist/cli/commands/status-capabilities.d.ts.map +1 -0
- package/dist/cli/daemon-client.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/daemon-status.d.ts +5 -0
- package/dist/cli/daemon-status.d.ts.map +1 -1
- package/dist/cli/daemon.d.ts +5 -0
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +660 -244
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/remote-manager.d.ts +6 -0
- package/dist/cli/remote-manager.d.ts.map +1 -1
- package/dist/cli/utils/parse.d.ts +1 -0
- package/dist/cli/utils/parse.d.ts.map +1 -1
- package/dist/cli/utils/skills.d.ts +1 -1
- package/dist/cli/utils/skills.d.ts.map +1 -1
- package/dist/cli/utils/workflow-message.d.ts +3 -0
- package/dist/cli/utils/workflow-message.d.ts.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/runtime-assemblies.d.ts +2 -1
- package/dist/core/runtime-assemblies.d.ts.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/desktop/runtime.d.ts +1 -0
- package/dist/desktop/runtime.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +729 -448
- package/dist/index.js.map +1 -1
- package/dist/inspiredesign/handoff.d.ts +34 -0
- package/dist/inspiredesign/handoff.d.ts.map +1 -0
- package/dist/opendevbrowser.d.ts.map +1 -1
- package/dist/opendevbrowser.js +729 -448
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/browser-fallback.d.ts.map +1 -1
- package/dist/providers/constraint.d.ts +11 -0
- package/dist/providers/constraint.d.ts.map +1 -1
- package/dist/providers/cookie-source.d.ts +8 -0
- package/dist/providers/cookie-source.d.ts.map +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/inspiredesign-capture.d.ts +17 -0
- package/dist/providers/inspiredesign-capture.d.ts.map +1 -0
- package/dist/providers/inspiredesign-contract.d.ts +110 -0
- package/dist/providers/inspiredesign-contract.d.ts.map +1 -0
- package/dist/providers/renderer.d.ts +23 -0
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/runtime-bundle.d.ts +2 -1
- package/dist/providers/runtime-bundle.d.ts.map +1 -1
- package/dist/providers/runtime-factory.d.ts +4 -2
- package/dist/providers/runtime-factory.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts +1 -1
- package/dist/providers/types.d.ts +3 -2
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/workflow-contracts.d.ts +1 -1
- package/dist/providers/workflow-contracts.d.ts.map +1 -1
- package/dist/providers/workflow-handoff.d.ts +14 -0
- package/dist/providers/workflow-handoff.d.ts.map +1 -0
- package/dist/providers/workflows.d.ts +21 -2
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-G36AM3Z2.js → providers-ZIVHHH4F.js} +6 -2
- package/dist/public-surface/generated-manifest.d.ts +143 -7
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +102 -3
- package/dist/public-surface/source.d.ts.map +1 -1
- package/dist/relay/protocol.d.ts +1 -1
- package/dist/relay/protocol.d.ts.map +1 -1
- package/dist/relay/relay-server.d.ts +1 -0
- package/dist/relay/relay-server.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +1 -1
- package/dist/tools/automation-shared.d.ts +6 -0
- package/dist/tools/automation-shared.d.ts.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/inspiredesign_run.d.ts +4 -0
- package/dist/tools/inspiredesign_run.d.ts.map +1 -0
- package/dist/tools/review_desktop.d.ts +4 -0
- package/dist/tools/review_desktop.d.ts.map +1 -0
- package/dist/tools/session_inspector.d.ts.map +1 -1
- package/dist/tools/session_inspector_audit.d.ts +4 -0
- package/dist/tools/session_inspector_audit.d.ts.map +1 -0
- package/dist/tools/session_inspector_plan.d.ts +4 -0
- package/dist/tools/session_inspector_plan.d.ts.map +1 -0
- package/dist/tools/status_capabilities.d.ts +4 -0
- package/dist/tools/status_capabilities.d.ts.map +1 -0
- package/extension/dist/background.js +70 -10
- package/extension/dist/canvas/canvas-runtime.js +14 -1
- package/extension/dist/ops/ops-runtime.js +18 -1
- package/extension/dist/popup.js +29 -16
- package/extension/dist/services/ConnectionManager.js +27 -2
- package/extension/manifest.json +1 -1
- package/extension/popup.html +11 -0
- package/package.json +5 -5
- package/skills/AGENTS.md +2 -2
- package/skills/opendevbrowser-best-practices/SKILL.md +50 -15
- package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +31 -12
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +64 -15
- package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +4 -0
- package/skills/opendevbrowser-best-practices/artifacts/skill-runtime-surface-matrix.md +11 -10
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-blocker-checklist.json +28 -22
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-generation-plan.v1.json +18 -17
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-handshake-example.json +135 -17
- package/skills/opendevbrowser-best-practices/assets/templates/skill-runtime-pack-matrix.json +55 -8
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +18 -4
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +16 -4
- package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +3 -1
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +68 -25
- package/skills/opendevbrowser-design-agent/SKILL.md +9 -4
- package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +15 -6
- package/skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json +18 -17
- package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +11 -0
- package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +57 -0
- package/skills/opendevbrowser-product-presentation-asset/SKILL.md +2 -2
- package/dist/chunk-5FZQJRBQ.js.map +0 -1
- package/dist/chunk-W4IHGDXV.js.map +0 -1
- package/dist/chunk-YBQECXZX.js.map +0 -1
- /package/dist/{providers-G36AM3Z2.js.map → providers-ZIVHHH4F.js.map} +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SessionInspectorHandle } from "../browser/manager-types";
|
|
2
|
+
import type { AutomationCoordinatorLike } from "../automation/coordinator";
|
|
3
|
+
import type { ToolDeps } from "./deps";
|
|
4
|
+
export declare function requireAutomationCoordinator(deps: ToolDeps): AutomationCoordinatorLike | string;
|
|
5
|
+
export declare function requireSessionInspectorHandle(deps: ToolDeps): SessionInspectorHandle | string;
|
|
6
|
+
//# sourceMappingURL=automation-shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automation-shared.d.ts","sourceRoot":"","sources":["../../src/tools/automation-shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGvC,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,GACb,yBAAyB,GAAG,MAAM,CAGpC;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,GACb,sBAAsB,GAAG,MAAM,CAOjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAwEvC,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,eAAO,MAAM,qBAAqB,aAAiD,CAAC;AAEpF,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAoG1E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspiredesign_run.d.ts","sourceRoot":"","sources":["../../src/tools/inspiredesign_run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAYvC,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAgDzE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review_desktop.d.ts","sourceRoot":"","sources":["../../src/tools/review_desktop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAMvC,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CA6BtE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session_inspector.d.ts","sourceRoot":"","sources":["../../src/tools/session_inspector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"session_inspector.d.ts","sourceRoot":"","sources":["../../src/tools/session_inspector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAMvC,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAqCzE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_inspector_audit.d.ts","sourceRoot":"","sources":["../../src/tools/session_inspector_audit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAUvC,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CA6D9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_inspector_plan.d.ts","sourceRoot":"","sources":["../../src/tools/session_inspector_plan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAOvC,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAyB7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status_capabilities.d.ts","sourceRoot":"","sources":["../../src/tools/status_capabilities.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAOvC,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAyB3E"}
|
|
@@ -27,6 +27,7 @@ const nativePort = new NativePortManager({
|
|
|
27
27
|
},
|
|
28
28
|
onDisconnect: () => {
|
|
29
29
|
updateBadge(getEffectiveStatus());
|
|
30
|
+
void refreshBadgeFromBackgroundStatus();
|
|
30
31
|
}
|
|
31
32
|
});
|
|
32
33
|
let autoConnectInFlight = false;
|
|
@@ -49,6 +50,7 @@ const LAST_AGENT_ANNOTATION_PAYLOAD_KEY = "annotationAgentPayloadSansScreenshots
|
|
|
49
50
|
const LAST_ANNOTATABLE_TAB_ID_KEY = "annotationLastTabId";
|
|
50
51
|
const POPUP_ANNOTATION_TARGET_TTL_MS = 10_000;
|
|
51
52
|
const BADGE_CONNECTED_DOT_COLOR = "#16a34a";
|
|
53
|
+
const BADGE_WARNING_DOT_COLOR = "#f59e0b";
|
|
52
54
|
const BADGE_DISCONNECTED_DOT_COLOR = "#dc2626";
|
|
53
55
|
const annotationSessions = new Map();
|
|
54
56
|
let lastAnnotationFull = null;
|
|
@@ -66,9 +68,12 @@ connection.onOpsMessage((message) => {
|
|
|
66
68
|
connection.onCanvasMessage((message) => {
|
|
67
69
|
canvasRuntime.handleMessage(message);
|
|
68
70
|
});
|
|
69
|
-
const updateBadge = (
|
|
70
|
-
const
|
|
71
|
-
|
|
71
|
+
const updateBadge = (tone) => {
|
|
72
|
+
const dotColor = tone === "connected"
|
|
73
|
+
? BADGE_CONNECTED_DOT_COLOR
|
|
74
|
+
: tone === "warning"
|
|
75
|
+
? BADGE_WARNING_DOT_COLOR
|
|
76
|
+
: BADGE_DISCONNECTED_DOT_COLOR;
|
|
72
77
|
chrome.action.setBadgeText({ text: "●" });
|
|
73
78
|
if (typeof chrome.action.setBadgeTextColor === "function") {
|
|
74
79
|
chrome.action.setBadgeTextColor({ color: dotColor });
|
|
@@ -86,10 +91,31 @@ const getEffectiveStatus = () => {
|
|
|
86
91
|
}
|
|
87
92
|
return "disconnected";
|
|
88
93
|
};
|
|
94
|
+
const hasReadyRelayHandshake = (health) => {
|
|
95
|
+
return health?.extensionConnected === true && health.extensionHandshakeComplete === true;
|
|
96
|
+
};
|
|
97
|
+
const deriveBackgroundStatus = (relayStatus, nativeHealth, relayHealth, reconnectSuppressed) => {
|
|
98
|
+
if (relayStatus === "connected") {
|
|
99
|
+
return "connected";
|
|
100
|
+
}
|
|
101
|
+
if (nativeHealth?.status === "connected") {
|
|
102
|
+
return "connected";
|
|
103
|
+
}
|
|
104
|
+
if (reconnectSuppressed) {
|
|
105
|
+
return "disconnected";
|
|
106
|
+
}
|
|
107
|
+
return hasReadyRelayHandshake(relayHealth) ? "connected" : "disconnected";
|
|
108
|
+
};
|
|
109
|
+
const deriveBadgeTone = (status, relayHealth) => {
|
|
110
|
+
if (status === "connected") {
|
|
111
|
+
return "connected";
|
|
112
|
+
}
|
|
113
|
+
return hasReadyRelayHandshake(relayHealth) ? "warning" : "disconnected";
|
|
114
|
+
};
|
|
89
115
|
const buildStatusMessage = async () => {
|
|
90
116
|
const error = connection.getLastError();
|
|
91
117
|
const relayStatus = connection.getStatus();
|
|
92
|
-
const
|
|
118
|
+
const reconnectSuppressed = connection.isReconnectSuppressed();
|
|
93
119
|
let note = error?.message;
|
|
94
120
|
let relayHealth = null;
|
|
95
121
|
const isNativeEnabled = nativeEnabled;
|
|
@@ -123,12 +149,18 @@ const buildStatusMessage = async () => {
|
|
|
123
149
|
});
|
|
124
150
|
const port = parsePort(stored.relayPort) ?? DEFAULT_RELAY_PORT;
|
|
125
151
|
relayHealth = await fetchRelayHealth(port);
|
|
126
|
-
|
|
127
|
-
|
|
152
|
+
if (hasReadyRelayHandshake(relayHealth)) {
|
|
153
|
+
note = `Connected to 127.0.0.1:${port}`;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
note = statusNoteOverride ?? buildRelayHealthNote(relayHealth);
|
|
157
|
+
}
|
|
158
|
+
if (!hasReadyRelayHandshake(relayHealth) && !statusNoteOverride && isNativeEnabled && nativeHealth?.status === "error") {
|
|
128
159
|
note = buildNativeHealthNote(nativeHealth);
|
|
129
160
|
}
|
|
130
161
|
}
|
|
131
162
|
}
|
|
163
|
+
const status = deriveBackgroundStatus(relayStatus, nativeHealth, relayHealth, reconnectSuppressed);
|
|
132
164
|
if (!error) {
|
|
133
165
|
const relayNotice = connection.getRelayNotice();
|
|
134
166
|
if (relayNotice) {
|
|
@@ -144,6 +176,21 @@ const buildStatusMessage = async () => {
|
|
|
144
176
|
nativeEnabled: isNativeEnabled
|
|
145
177
|
};
|
|
146
178
|
};
|
|
179
|
+
let badgeRefreshVersion = 0;
|
|
180
|
+
const refreshBadgeFromBackgroundStatus = async () => {
|
|
181
|
+
const refreshVersion = ++badgeRefreshVersion;
|
|
182
|
+
let tone = getEffectiveStatus();
|
|
183
|
+
try {
|
|
184
|
+
const statusMessage = await buildStatusMessage();
|
|
185
|
+
tone = deriveBadgeTone(statusMessage.status, statusMessage.relayHealth ?? null);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Keep the synchronous local status when relay/native health cannot be fetched.
|
|
189
|
+
}
|
|
190
|
+
if (refreshVersion === badgeRefreshVersion) {
|
|
191
|
+
updateBadge(tone);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
147
194
|
const setStorage = (items) => {
|
|
148
195
|
return new Promise((resolve) => {
|
|
149
196
|
chrome.storage.local.set(items, () => resolve());
|
|
@@ -248,6 +295,7 @@ const attemptNativeConnect = async () => {
|
|
|
248
295
|
logError("native_port.ping", error, { code: "native_ping_failed" });
|
|
249
296
|
}
|
|
250
297
|
updateBadge(getEffectiveStatus());
|
|
298
|
+
await refreshBadgeFromBackgroundStatus();
|
|
251
299
|
return nativePort.isConnected();
|
|
252
300
|
};
|
|
253
301
|
const parsePort = (value) => {
|
|
@@ -1271,7 +1319,7 @@ const attemptAutoConnect = async () => {
|
|
|
1271
1319
|
});
|
|
1272
1320
|
const autoConnect = typeof data.autoConnect === "boolean" ? data.autoConnect : DEFAULT_AUTO_CONNECT;
|
|
1273
1321
|
autoConnectEnabled = autoConnect;
|
|
1274
|
-
if (!autoConnect || connection.getStatus() === "connected") {
|
|
1322
|
+
if (!autoConnect || connection.getStatus() === "connected" || connection.isReconnectSuppressed()) {
|
|
1275
1323
|
clearRetry();
|
|
1276
1324
|
return;
|
|
1277
1325
|
}
|
|
@@ -1382,6 +1430,7 @@ const autoConnect = async () => {
|
|
|
1382
1430
|
connection.onStatus((status) => {
|
|
1383
1431
|
const effectiveStatus = status === "connected" ? "connected" : (nativeEnabled && nativePort.isConnected()) ? "connected" : "disconnected";
|
|
1384
1432
|
updateBadge(effectiveStatus);
|
|
1433
|
+
void refreshBadgeFromBackgroundStatus();
|
|
1385
1434
|
if (status === "connected") {
|
|
1386
1435
|
nativePort.disconnect();
|
|
1387
1436
|
setStatusNoteOverride(null);
|
|
@@ -1392,6 +1441,10 @@ connection.onStatus((status) => {
|
|
|
1392
1441
|
clearTimeout(session.timeoutId);
|
|
1393
1442
|
}
|
|
1394
1443
|
annotationSessions.clear();
|
|
1444
|
+
if (connection.isReconnectSuppressed()) {
|
|
1445
|
+
clearRetry();
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1395
1448
|
if (autoConnectEnabled) {
|
|
1396
1449
|
scheduleRetry();
|
|
1397
1450
|
}
|
|
@@ -1471,6 +1524,7 @@ chrome.storage.onChanged.addListener((changes, area) => {
|
|
|
1471
1524
|
nativePort.disconnect();
|
|
1472
1525
|
}
|
|
1473
1526
|
updateBadge(getEffectiveStatus());
|
|
1527
|
+
void refreshBadgeFromBackgroundStatus();
|
|
1474
1528
|
}
|
|
1475
1529
|
if (changes.autoConnect) {
|
|
1476
1530
|
autoConnectEnabled =
|
|
@@ -1496,7 +1550,9 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1496
1550
|
};
|
|
1497
1551
|
if (message.type === "status") {
|
|
1498
1552
|
(async () => {
|
|
1499
|
-
|
|
1553
|
+
const statusMessage = await buildStatusMessage();
|
|
1554
|
+
updateBadge(deriveBadgeTone(statusMessage.status, statusMessage.relayHealth ?? null));
|
|
1555
|
+
respond(statusMessage);
|
|
1500
1556
|
})().catch((error) => {
|
|
1501
1557
|
logError("popup.status", error, { code: "status_failed" });
|
|
1502
1558
|
respond({
|
|
@@ -1513,7 +1569,9 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1513
1569
|
if (connection.getStatus() !== "connected") {
|
|
1514
1570
|
await attemptNativeConnect();
|
|
1515
1571
|
}
|
|
1516
|
-
|
|
1572
|
+
const statusMessage = await buildStatusMessage();
|
|
1573
|
+
updateBadge(deriveBadgeTone(statusMessage.status, statusMessage.relayHealth ?? null));
|
|
1574
|
+
respond(statusMessage);
|
|
1517
1575
|
})().catch((error) => {
|
|
1518
1576
|
logError("popup.connect", error, { code: "connect_failed" });
|
|
1519
1577
|
connection.disconnect();
|
|
@@ -1531,7 +1589,9 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1531
1589
|
await connection.disconnect();
|
|
1532
1590
|
nativePort.disconnect();
|
|
1533
1591
|
connection.clearLastError();
|
|
1534
|
-
|
|
1592
|
+
const statusMessage = await buildStatusMessage();
|
|
1593
|
+
updateBadge(deriveBadgeTone(statusMessage.status, statusMessage.relayHealth ?? null));
|
|
1594
|
+
respond(statusMessage);
|
|
1535
1595
|
})().catch((error) => {
|
|
1536
1596
|
logError("popup.disconnect", error, { code: "disconnect_failed" });
|
|
1537
1597
|
connection.disconnect();
|
|
@@ -180,6 +180,9 @@ export class CanvasRuntime {
|
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
182
|
for (const session of this.sessions.listOwnedBy(clientId)) {
|
|
183
|
+
if (this.shouldPreserveSessionOnDisconnect(session)) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
183
186
|
void this.closeRuntimeSession(session, "client_disconnected");
|
|
184
187
|
}
|
|
185
188
|
for (const [sessionId, session] of this.overlaySessions.entries()) {
|
|
@@ -524,6 +527,10 @@ export class CanvasRuntime {
|
|
|
524
527
|
overlayState: result?.overlayState ?? "mounted"
|
|
525
528
|
};
|
|
526
529
|
}
|
|
530
|
+
shouldPreserveSessionOnDisconnect(session) {
|
|
531
|
+
return typeof session.designTabTargetId === "string"
|
|
532
|
+
&& session.targets.has(session.designTabTargetId);
|
|
533
|
+
}
|
|
527
534
|
createOrReplaceSession(message, tabId, document, previewMode, record) {
|
|
528
535
|
const canvasSessionId = resolveCanvasSessionId(message, record);
|
|
529
536
|
const clientId = requireString(message.clientId, "clientId");
|
|
@@ -632,7 +639,13 @@ export class CanvasRuntime {
|
|
|
632
639
|
const session = resolveSessionForMessage(this.sessions, message, payload);
|
|
633
640
|
const clientId = requireString(message.clientId, "clientId");
|
|
634
641
|
const leaseId = optionalString(message.leaseId);
|
|
635
|
-
if (session.ownerClientId !== clientId
|
|
642
|
+
if (session.ownerClientId !== clientId) {
|
|
643
|
+
if (!leaseId || session.leaseId !== leaseId) {
|
|
644
|
+
throw new Error("Canvas session ownership mismatch.");
|
|
645
|
+
}
|
|
646
|
+
session.ownerClientId = clientId;
|
|
647
|
+
}
|
|
648
|
+
if (leaseId && session.leaseId !== leaseId) {
|
|
636
649
|
throw new Error("Canvas session ownership mismatch.");
|
|
637
650
|
}
|
|
638
651
|
return session;
|
|
@@ -3570,7 +3570,12 @@ export class OpsRuntime {
|
|
|
3570
3570
|
this.sendError(message, buildError("invalid_request", "No active target", false));
|
|
3571
3571
|
return null;
|
|
3572
3572
|
}
|
|
3573
|
-
|
|
3573
|
+
let target = this.resolveRequestedTargetContext(session, targetId, explicitTargetId !== null);
|
|
3574
|
+
if (!target
|
|
3575
|
+
&& explicitTargetId !== null
|
|
3576
|
+
&& this.shouldRecoverExplicitCanvasOverlayTarget(message.command, targetId)) {
|
|
3577
|
+
target = this.recoverExplicitCanvasOverlayTarget(session, targetId);
|
|
3578
|
+
}
|
|
3574
3579
|
if (!target) {
|
|
3575
3580
|
this.sendError(message, buildError("invalid_request", "Active target missing", false));
|
|
3576
3581
|
return null;
|
|
@@ -3592,6 +3597,18 @@ export class OpsRuntime {
|
|
|
3592
3597
|
}
|
|
3593
3598
|
return target;
|
|
3594
3599
|
}
|
|
3600
|
+
shouldRecoverExplicitCanvasOverlayTarget(command, targetId) {
|
|
3601
|
+
return command.startsWith("canvas.overlay.") && parseTabTargetId(targetId) !== null;
|
|
3602
|
+
}
|
|
3603
|
+
recoverExplicitCanvasOverlayTarget(session, targetId) {
|
|
3604
|
+
const tabId = parseTabTargetId(targetId);
|
|
3605
|
+
if (tabId === null) {
|
|
3606
|
+
return null;
|
|
3607
|
+
}
|
|
3608
|
+
const recoveredTarget = session.targets.get(targetId) ?? this.sessions.addTarget(session.id, tabId);
|
|
3609
|
+
session.activeTargetId = recoveredTarget.targetId;
|
|
3610
|
+
return this.resolveRequestedTargetContext(session, recoveredTarget.targetId, true);
|
|
3611
|
+
}
|
|
3595
3612
|
isAllowedCanvasRestrictionTarget(session, targetId, target) {
|
|
3596
3613
|
if (this.isAllowedCanvasTargetUrl(target.url)) {
|
|
3597
3614
|
return true;
|
package/extension/dist/popup.js
CHANGED
|
@@ -82,18 +82,31 @@ const setHealthNote = (message) => {
|
|
|
82
82
|
currentHealthNote = next;
|
|
83
83
|
healthNote.textContent = next;
|
|
84
84
|
};
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
const hasRelayHealthyMismatch = (response) => {
|
|
86
|
+
return response.status === "disconnected"
|
|
87
|
+
&& response.relayHealth?.extensionConnected === true
|
|
88
|
+
&& response.relayHealth.extensionHandshakeComplete === true;
|
|
89
|
+
};
|
|
90
|
+
const applyStatusTone = (label, tone) => {
|
|
91
|
+
const isConnected = tone === "connected";
|
|
92
|
+
const isWarning = tone === "warning";
|
|
93
|
+
statusEl.textContent = label;
|
|
88
94
|
toggleButton.textContent = isConnected ? "Disconnect" : "Connect";
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
statusIndicator.classList.toggle("connected", isConnected);
|
|
96
|
+
statusPill.classList.toggle("connected", isConnected);
|
|
97
|
+
statusIndicator.classList.toggle("warning", isWarning);
|
|
98
|
+
statusPill.classList.toggle("warning", isWarning);
|
|
99
|
+
};
|
|
100
|
+
const setStatus = (response) => {
|
|
101
|
+
if (response.status === "connected") {
|
|
102
|
+
applyStatusTone("Connected", "connected");
|
|
103
|
+
return;
|
|
92
104
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
105
|
+
if (hasRelayHealthyMismatch(response)) {
|
|
106
|
+
applyStatusTone("Relay active", "warning");
|
|
107
|
+
return;
|
|
96
108
|
}
|
|
109
|
+
applyStatusTone("Disconnected", "disconnected");
|
|
97
110
|
};
|
|
98
111
|
const setHealthValue = (element, value, tone) => {
|
|
99
112
|
element.textContent = value;
|
|
@@ -180,7 +193,7 @@ const setNativeHealth = (health, enabled) => {
|
|
|
180
193
|
}
|
|
181
194
|
};
|
|
182
195
|
const applyStatus = (response) => {
|
|
183
|
-
setStatus(response
|
|
196
|
+
setStatus(response);
|
|
184
197
|
setNote(response.note);
|
|
185
198
|
setHealth(response.relayHealth ?? null);
|
|
186
199
|
setNativeHealth(response.nativeHealth ?? null, response.nativeEnabled === true);
|
|
@@ -239,7 +252,7 @@ const refreshStatus = async () => {
|
|
|
239
252
|
}
|
|
240
253
|
catch (error) {
|
|
241
254
|
logError("popup.status_refresh", error, { code: "status_refresh_failed" });
|
|
242
|
-
setStatus("disconnected");
|
|
255
|
+
setStatus({ status: "disconnected", relayHealth: null });
|
|
243
256
|
const message = error instanceof Error ? error.message : "Background unavailable";
|
|
244
257
|
setNote(message);
|
|
245
258
|
setHealth(null);
|
|
@@ -563,7 +576,7 @@ const toggle = async () => {
|
|
|
563
576
|
});
|
|
564
577
|
}
|
|
565
578
|
else {
|
|
566
|
-
setStatus("disconnected");
|
|
579
|
+
setStatus({ status: "disconnected", relayHealth: null });
|
|
567
580
|
setNote("Auto-pair failed. Start the daemon and retry.");
|
|
568
581
|
setTimeout(() => refreshStatus(), 2000);
|
|
569
582
|
return;
|
|
@@ -579,7 +592,7 @@ const toggle = async () => {
|
|
|
579
592
|
}
|
|
580
593
|
catch (error) {
|
|
581
594
|
logError("popup.toggle", error, { code: "toggle_failed" });
|
|
582
|
-
setStatus("disconnected");
|
|
595
|
+
setStatus({ status: "disconnected", relayHealth: null });
|
|
583
596
|
const message = error instanceof Error ? error.message : "Background unavailable";
|
|
584
597
|
setNote(message);
|
|
585
598
|
setHealth(null);
|
|
@@ -588,7 +601,7 @@ const toggle = async () => {
|
|
|
588
601
|
toggleButton.addEventListener("click", () => {
|
|
589
602
|
toggle().catch((error) => {
|
|
590
603
|
logError("popup.toggle", error, { code: "toggle_failed" });
|
|
591
|
-
setStatus("disconnected");
|
|
604
|
+
setStatus({ status: "disconnected", relayHealth: null });
|
|
592
605
|
});
|
|
593
606
|
});
|
|
594
607
|
annotationStartButton.addEventListener("click", () => {
|
|
@@ -663,7 +676,7 @@ autoConnectInput.addEventListener("change", () => {
|
|
|
663
676
|
if (enabled && statusEl.textContent !== "Connected") {
|
|
664
677
|
toggle().catch((error) => {
|
|
665
678
|
logError("popup.auto_connect", error, { code: "auto_connect_failed" });
|
|
666
|
-
setStatus("disconnected");
|
|
679
|
+
setStatus({ status: "disconnected", relayHealth: null });
|
|
667
680
|
setNote();
|
|
668
681
|
});
|
|
669
682
|
}
|
|
@@ -702,7 +715,7 @@ relayPortInput.addEventListener("input", () => {
|
|
|
702
715
|
});
|
|
703
716
|
refreshStatus().catch((error) => {
|
|
704
717
|
logError("popup.refresh_status", error, { code: "status_refresh_failed" });
|
|
705
|
-
setStatus("disconnected");
|
|
718
|
+
setStatus({ status: "disconnected", relayHealth: null });
|
|
706
719
|
setNote();
|
|
707
720
|
});
|
|
708
721
|
loadSettings().catch((error) => {
|
|
@@ -65,6 +65,7 @@ export class ConnectionManager {
|
|
|
65
65
|
relayEpoch = null;
|
|
66
66
|
relayConfirmedPort = null;
|
|
67
67
|
relayNotice = null;
|
|
68
|
+
reconnectSuppressed = false;
|
|
68
69
|
maxReconnectDelayMs = RECONNECT_MAX_DELAY_MS;
|
|
69
70
|
connectPromise = null;
|
|
70
71
|
annotationHandler = null;
|
|
@@ -96,6 +97,9 @@ export class ConnectionManager {
|
|
|
96
97
|
getRelayNotice() {
|
|
97
98
|
return this.relayNotice;
|
|
98
99
|
}
|
|
100
|
+
isReconnectSuppressed() {
|
|
101
|
+
return this.reconnectSuppressed;
|
|
102
|
+
}
|
|
99
103
|
getLastError() {
|
|
100
104
|
return this.lastError;
|
|
101
105
|
}
|
|
@@ -245,6 +249,7 @@ export class ConnectionManager {
|
|
|
245
249
|
}
|
|
246
250
|
try {
|
|
247
251
|
this.clearLastError();
|
|
252
|
+
this.reconnectSuppressed = false;
|
|
248
253
|
this.relayNotice = null;
|
|
249
254
|
this.shouldReconnect = true;
|
|
250
255
|
this.reconnectAttempts = 0;
|
|
@@ -275,6 +280,7 @@ export class ConnectionManager {
|
|
|
275
280
|
if (this.disconnecting)
|
|
276
281
|
return;
|
|
277
282
|
this.disconnecting = true;
|
|
283
|
+
this.reconnectSuppressed = false;
|
|
278
284
|
this.shouldReconnect = false;
|
|
279
285
|
this.clearReconnectTimer();
|
|
280
286
|
this.stopHeartbeat();
|
|
@@ -512,7 +518,7 @@ export class ConnectionManager {
|
|
|
512
518
|
this.canvasHandler?.(message);
|
|
513
519
|
},
|
|
514
520
|
onClose: (detail) => {
|
|
515
|
-
this.handleRelayClose(detail);
|
|
521
|
+
this.handleRelayClose(relay, detail);
|
|
516
522
|
}
|
|
517
523
|
});
|
|
518
524
|
this.relay = relay;
|
|
@@ -563,10 +569,25 @@ export class ConnectionManager {
|
|
|
563
569
|
throw new ConnectionError("relay_connect_failed", "Relay connection failed. Start the daemon and retry.");
|
|
564
570
|
}
|
|
565
571
|
}
|
|
566
|
-
handleRelayClose(detail) {
|
|
572
|
+
handleRelayClose(closedRelay, detail) {
|
|
573
|
+
if (this.relay !== closedRelay) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
567
576
|
this.stopHeartbeat();
|
|
568
577
|
this.relay = null;
|
|
569
578
|
this.cdp.markClientClosed();
|
|
579
|
+
if (this.isRelayReplacedByNewClient(detail)) {
|
|
580
|
+
this.reconnectSuppressed = true;
|
|
581
|
+
this.shouldReconnect = false;
|
|
582
|
+
this.clearReconnectTimer();
|
|
583
|
+
this.setStatus("disconnected");
|
|
584
|
+
this.relayInstanceId = null;
|
|
585
|
+
this.relayConfirmedPort = null;
|
|
586
|
+
this.relayEpoch = null;
|
|
587
|
+
this.relayNotice = "Another extension client took over the relay connection. This client will stay disconnected until you reconnect it explicitly.";
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
this.reconnectSuppressed = false;
|
|
570
591
|
if (detail && (detail.code === 1008 || detail.reason?.includes("Invalid pairing token"))) {
|
|
571
592
|
this.clearStoredPairingToken();
|
|
572
593
|
}
|
|
@@ -1005,11 +1026,15 @@ export class ConnectionManager {
|
|
|
1005
1026
|
this.reconnectTimer = null;
|
|
1006
1027
|
}
|
|
1007
1028
|
}
|
|
1029
|
+
isRelayReplacedByNewClient(detail) {
|
|
1030
|
+
return detail?.reason === "Replaced by a new extension client";
|
|
1031
|
+
}
|
|
1008
1032
|
async verifyHandshakeHealth(relay, source) {
|
|
1009
1033
|
try {
|
|
1010
1034
|
const health = await relay.sendPing(this.heartbeatTimeoutMs);
|
|
1011
1035
|
if (health.extensionConnected && health.extensionHandshakeComplete) {
|
|
1012
1036
|
if (this.relay === relay) {
|
|
1037
|
+
this.reconnectSuppressed = false;
|
|
1013
1038
|
this.relayNotice = null;
|
|
1014
1039
|
}
|
|
1015
1040
|
return true;
|
package/extension/manifest.json
CHANGED
package/extension/popup.html
CHANGED
|
@@ -126,6 +126,12 @@
|
|
|
126
126
|
background: var(--accent-soft);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
.status-pill.warning {
|
|
130
|
+
color: var(--text);
|
|
131
|
+
border-color: rgba(245, 158, 11, 0.55);
|
|
132
|
+
background: rgba(245, 158, 11, 0.18);
|
|
133
|
+
}
|
|
134
|
+
|
|
129
135
|
.status-indicator {
|
|
130
136
|
width: 8px;
|
|
131
137
|
height: 8px;
|
|
@@ -140,6 +146,11 @@
|
|
|
140
146
|
box-shadow: 0 0 12px rgba(32, 213, 198, 0.55);
|
|
141
147
|
}
|
|
142
148
|
|
|
149
|
+
.status-indicator.warning {
|
|
150
|
+
background: #f59e0b;
|
|
151
|
+
box-shadow: 0 0 12px rgba(245, 158, 11, 0.45);
|
|
152
|
+
}
|
|
153
|
+
|
|
143
154
|
.panel {
|
|
144
155
|
position: relative;
|
|
145
156
|
display: flex;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opendevbrowser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Browser automation runtime with snapshot-refs-actions, browser replay screencasts, public read-only desktop observation, and browser-scoped computer-use orchestration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"node": ">=18"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "tsup src/index.ts src/cli/index.ts src/skills/skill-loader.ts --format esm --clean --sourcemap && tsc --emitDeclarationOnly --declaration --declarationMap -p tsconfig.json && node scripts/postbuild-dist.mjs",
|
|
48
|
+
"build": "node scripts/run-package-tool.mjs tsup src/index.ts src/cli/index.ts src/skills/skill-loader.ts --format esm --clean --sourcemap && node scripts/run-package-tool.mjs tsc --emitDeclarationOnly --declaration --declarationMap -p tsconfig.json && node scripts/postbuild-dist.mjs",
|
|
49
49
|
"dev": "tsup src/index.ts src/cli/index.ts src/skills/skill-loader.ts --format esm --dts --watch",
|
|
50
|
-
"lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
51
|
-
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
50
|
+
"lint": "node scripts/run-package-tool.mjs eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
51
|
+
"typecheck": "node scripts/run-package-tool.mjs tsc --noEmit -p tsconfig.json",
|
|
52
52
|
"test": "node scripts/run-vitest-coverage.mjs",
|
|
53
53
|
"test:release-gate": "node scripts/release-gate-test-groups.mjs",
|
|
54
54
|
"test:release-gate:g1": "node scripts/release-gate-test-groups.mjs --group 1",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"test:release-gate:g4": "node scripts/release-gate-test-groups.mjs --group 4",
|
|
58
58
|
"test:release-gate:g5": "node scripts/release-gate-test-groups.mjs --group 5",
|
|
59
59
|
"extension:sync": "node scripts/sync-extension-version.mjs",
|
|
60
|
-
"extension:build": "npm run extension:sync && tsc -p extension/tsconfig.json && node scripts/copy-extension-assets.mjs",
|
|
60
|
+
"extension:build": "npm run extension:sync && node scripts/run-package-tool.mjs tsc -p extension/tsconfig.json && node scripts/copy-extension-assets.mjs",
|
|
61
61
|
"extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html canvas.html dist/ icons/",
|
|
62
62
|
"extension:store": "node scripts/chrome-store-publish.mjs",
|
|
63
63
|
"version:check": "node scripts/verify-versions.mjs",
|
package/skills/AGENTS.md
CHANGED
|
@@ -39,9 +39,9 @@ Content organized by topic for filtering.
|
|
|
39
39
|
3. `.codex/skills/` (project compatibility)
|
|
40
40
|
4. `$CODEX_HOME/skills` (global compatibility; fallback `~/.codex/skills`)
|
|
41
41
|
5. `.claude/skills/` (ClaudeCode project compatibility)
|
|
42
|
-
6. `$CLAUDECODE_HOME/skills`
|
|
42
|
+
6. `$CLAUDECODE_HOME/skills` (ClaudeCode global compatibility; fallback `~/.claude/skills`)
|
|
43
43
|
7. `.amp/skills/` (AmpCLI project compatibility)
|
|
44
|
-
8. `$
|
|
44
|
+
8. `$AMP_CLI_HOME/skills` (AmpCLI global compatibility; fallback `~/.amp/skills`)
|
|
45
45
|
9. `skillPaths` config (custom)
|
|
46
46
|
10. Bundled package `skills/` directory as a fallback when no installed copy is available
|
|
47
47
|
|