@openengio/cli 0.24.3 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/public/openeng.js +63 -18
- package/package.json +1 -1
- package/skill/demo/SKILL.md +130 -103
- package/skill/openeng/SKILL.md +12 -0
package/bin/public/openeng.js
CHANGED
|
@@ -289,6 +289,11 @@ function doc(does, refuses) {
|
|
|
289
289
|
return Object.freeze({ does, refuses: Object.freeze([...refuses]) });
|
|
290
290
|
}
|
|
291
291
|
var ROUTE_DOCS = Object.freeze({
|
|
292
|
+
createObjectSet: doc("Saves a named set of 1 to 200 object addresses in the caller's organisation. Concurrent retries with one key return the same saved set and revision.", [...SCOPED, "head-moved"]),
|
|
293
|
+
listObjectSets: doc("Lists the organisation's saved sets, newest update first, without members or counts.", SIGNED_IN),
|
|
294
|
+
readObjectSet: doc("Reads a saved set's visible objects on the selected ref, a count of missing visible members and one bit for members outside the caller's scope.", [...SCOPED, "head-moved"]),
|
|
295
|
+
updateObjectSet: doc("Renames a saved set or replaces its readable members at the expected revision. Members outside the caller's scope remain. A success raises the revision by one.", [...SCOPED, "stale-revision", "head-moved"]),
|
|
296
|
+
deleteObjectSet: doc("Deletes a saved set and every member at the expected revision.", [...SCOPED, "stale-revision"]),
|
|
292
297
|
health: doc("Answers whether the host is running.", PUBLIC),
|
|
293
298
|
signInStart: doc("Starts a sign-in with the identity provider and redirects the browser to it.", PUBLIC),
|
|
294
299
|
signInCallback: doc("Receives the identity provider's answer and returns a one-time code for the client.", [...PUBLIC, "kind", "lifecycle", "invitation", "token-shape", "signature", "issuer", "audience", "expiry", "algorithm", "claims"]),
|
|
@@ -472,6 +477,11 @@ function deepFreeze(value) {
|
|
|
472
477
|
return value;
|
|
473
478
|
}
|
|
474
479
|
var SCHEMAS = {
|
|
480
|
+
createObjectSet: { "type": "object", "properties": { "name": { "type": "string" }, "members": { "type": "array", "items": { "type": "object", "properties": { "objectId": { "type": "string" }, "projectId": { "type": "string" } }, "required": ["objectId", "projectId"], "additionalProperties": false } } }, "required": ["name", "members"], "additionalProperties": false },
|
|
481
|
+
listObjectSets: { "type": "object", "properties": {}, "required": [], "additionalProperties": false },
|
|
482
|
+
readObjectSet: { "type": "object", "properties": { "setId": { "type": "string" } }, "required": ["setId"], "additionalProperties": false },
|
|
483
|
+
updateObjectSet: { "type": "object", "properties": { "setId": { "type": "string" }, "revision": { "type": "number" }, "name": { "type": "string" }, "members": { "type": "array", "items": { "type": "object", "properties": { "objectId": { "type": "string" }, "projectId": { "type": "string" } }, "required": ["objectId", "projectId"], "additionalProperties": false } } }, "required": ["setId", "revision"], "additionalProperties": false },
|
|
484
|
+
deleteObjectSet: { "type": "object", "properties": { "setId": { "type": "string" }, "revision": { "type": "number" } }, "required": ["setId", "revision"], "additionalProperties": false },
|
|
475
485
|
health: { "type": "object", "properties": {}, "required": [], "additionalProperties": false },
|
|
476
486
|
signInStart: { "type": "object", "properties": { "state": { "type": "string" }, "loopback": { "type": "string" }, "code_challenge": { "type": "string" }, "code_challenge_method": { "const": "S256" } }, "required": ["state", "loopback", "code_challenge", "code_challenge_method"], "additionalProperties": false },
|
|
477
487
|
signInCallback: { "oneOf": [{ "type": "object", "properties": { "state": { "type": "string" }, "code": { "type": "string" } }, "required": ["state", "code"], "additionalProperties": false }, { "type": "object", "properties": { "state": { "type": "string" }, "error": { "type": "string" } }, "required": ["state", "error"], "additionalProperties": false }] },
|
|
@@ -613,6 +623,11 @@ var SELECTORS = {
|
|
|
613
623
|
};
|
|
614
624
|
var SELECTOR_SCHEMAS = deepFreeze(SELECTORS);
|
|
615
625
|
var EXAMPLES = {
|
|
626
|
+
createObjectSet: { "name": "Saved set", "members": [{ "objectId": "obj_aaaaaaaaaaaaaaaaaaaaaaaaaa", "projectId": "<projectId>" }] },
|
|
627
|
+
listObjectSets: {},
|
|
628
|
+
readObjectSet: { "setId": "ost_aaaaaaaaaaaaaaaaaaaaaaaaaa" },
|
|
629
|
+
updateObjectSet: { "setId": "ost_aaaaaaaaaaaaaaaaaaaaaaaaaa", "revision": 1, "name": "Renamed set" },
|
|
630
|
+
deleteObjectSet: { "setId": "ost_aaaaaaaaaaaaaaaaaaaaaaaaaa", "revision": 1 },
|
|
616
631
|
health: {},
|
|
617
632
|
signInStart: { "state": "<state>", "loopback": "<loopback>", "code_challenge": "<code_challenge>", "code_challenge_method": "S256" },
|
|
618
633
|
signInCallback: { "state": "<state>", "code": "<code>" },
|
|
@@ -749,7 +764,7 @@ var EXAMPLES = {
|
|
|
749
764
|
var ROUTE_INPUT_EXAMPLES = deepFreeze(EXAMPLES);
|
|
750
765
|
|
|
751
766
|
// packages/api-contract/dist/routes.js
|
|
752
|
-
var PROTOCOL_VERSION =
|
|
767
|
+
var PROTOCOL_VERSION = 27;
|
|
753
768
|
var VERSION_HEADER = "oe2-protocol-version";
|
|
754
769
|
var TOKEN_HEADER = "authorization";
|
|
755
770
|
var IDEMPOTENCY_HEADER = "oe2-idempotency-key";
|
|
@@ -775,6 +790,11 @@ function route(entry2) {
|
|
|
775
790
|
return Object.freeze({ ...entry2, doc: documented });
|
|
776
791
|
}
|
|
777
792
|
var ROUTES = Object.freeze({
|
|
793
|
+
createObjectSet: route({ name: "createObjectSet", method: "POST", path: "/object-sets", group: "write", selector: "object", subject: "project", idempotent: true, admission: admitting("user"), versioned: true, module: "objects-sdk", capability: "objects.createObjectSet" }),
|
|
794
|
+
listObjectSets: route({ name: "listObjectSets", method: "POST", path: "/object-sets/list", group: "read", selector: "none", subject: "none", idempotent: false, admission: admitting("user"), versioned: true, module: "objects-sdk", capability: "objects.listObjectSets" }),
|
|
795
|
+
readObjectSet: route({ name: "readObjectSet", method: "POST", path: "/object-sets/read", group: "read", selector: "object", subject: "project", idempotent: false, admission: admitting("user"), versioned: true, module: "objects-sdk", capability: "objects.readObjectSet" }),
|
|
796
|
+
updateObjectSet: route({ name: "updateObjectSet", method: "POST", path: "/object-sets/update", group: "write", selector: "object", subject: "project", idempotent: false, admission: admitting("user"), versioned: true, module: "objects-sdk", capability: "objects.updateObjectSet" }),
|
|
797
|
+
deleteObjectSet: route({ name: "deleteObjectSet", method: "POST", path: "/object-sets/delete", group: "write", selector: "none", subject: "none", idempotent: false, admission: admitting("user"), versioned: true, module: "objects-sdk", capability: "objects.deleteObjectSet" }),
|
|
778
798
|
health: route({ name: "health", method: "GET", path: "/health", group: "platform", selector: "none", subject: "platform", idempotent: false, admission: NO_ACCESS_TOKEN, versioned: false, module: "sdk-core", capability: "core.health" }),
|
|
779
799
|
signInStart: route({ name: "signInStart", method: "GET", path: "/auth/sign-in", group: "platform", selector: "none", subject: "platform", idempotent: false, admission: NO_ACCESS_TOKEN, versioned: false, module: "sdk-core", capability: "core.signInStart" }),
|
|
780
800
|
signInCallback: route({ name: "signInCallback", method: "GET", path: "/auth/callback", group: "platform", selector: "none", subject: "platform", idempotent: false, admission: NO_ACCESS_TOKEN, versioned: false, module: "sdk-core", capability: "core.signInCallback" }),
|
|
@@ -909,6 +929,11 @@ var ROUTES = Object.freeze({
|
|
|
909
929
|
closeImportRun: route({ name: "closeImportRun", method: "POST", path: "/import-run-closes", group: "write", selector: "connection", subject: "connection", idempotent: false, admission: admitting("service", "user"), versioned: true, module: "admin-sdk", capability: "admin.importRunClose" })
|
|
910
930
|
});
|
|
911
931
|
var ROUTE_CARRIES_CREDENTIAL = Object.freeze({
|
|
932
|
+
createObjectSet: false,
|
|
933
|
+
listObjectSets: false,
|
|
934
|
+
readObjectSet: false,
|
|
935
|
+
updateObjectSet: false,
|
|
936
|
+
deleteObjectSet: false,
|
|
912
937
|
health: false,
|
|
913
938
|
signInStart: false,
|
|
914
939
|
signInCallback: true,
|
|
@@ -1057,7 +1082,7 @@ var CLIENT_SCOPES = Object.freeze({
|
|
|
1057
1082
|
offline_access: Object.freeze({ capabilities: Object.freeze([]), consentLine: "Stay connected when you are away, until you disconnect it." })
|
|
1058
1083
|
});
|
|
1059
1084
|
|
|
1060
|
-
// packages/sdk-
|
|
1085
|
+
// packages/sdk-dispatch/dist/explain.js
|
|
1061
1086
|
function explainKind(kind) {
|
|
1062
1087
|
if (!Object.hasOwn(BY_KIND, kind)) {
|
|
1063
1088
|
throw new Error(`the refusal kind ${JSON.stringify(kind)} has no entry in the refusal catalogue`);
|
|
@@ -1137,10 +1162,10 @@ function unauthenticatedEnvelope() {
|
|
|
1137
1162
|
return { version: PROTOCOL_VERSION, refusal: explainedRefusalOf({ kind: "unauthenticated" }), correlationId: null };
|
|
1138
1163
|
}
|
|
1139
1164
|
|
|
1140
|
-
// packages/sdk-
|
|
1165
|
+
// packages/sdk-dispatch/dist/socket-transport.js
|
|
1141
1166
|
import { request } from "node:http";
|
|
1142
1167
|
|
|
1143
|
-
// packages/sdk-
|
|
1168
|
+
// packages/sdk-dispatch/dist/response.js
|
|
1144
1169
|
function responseOf(status, text, reason) {
|
|
1145
1170
|
let read = false;
|
|
1146
1171
|
const members = {
|
|
@@ -1170,7 +1195,7 @@ function responseOf(status, text, reason) {
|
|
|
1170
1195
|
});
|
|
1171
1196
|
}
|
|
1172
1197
|
|
|
1173
|
-
// packages/sdk-
|
|
1198
|
+
// packages/sdk-dispatch/dist/socket-transport.js
|
|
1174
1199
|
var REQUEST_DEADLINE_MS = 1e4;
|
|
1175
1200
|
var HostOutcomeUnknown = class extends Error {
|
|
1176
1201
|
path;
|
|
@@ -1465,7 +1490,7 @@ function createHostStreamFetch(socketPath, headDeadlineMs = REQUEST_DEADLINE_MS)
|
|
|
1465
1490
|
};
|
|
1466
1491
|
}
|
|
1467
1492
|
|
|
1468
|
-
// packages/sdk-
|
|
1493
|
+
// packages/sdk-dispatch/dist/call.js
|
|
1469
1494
|
function isEnvelope(value) {
|
|
1470
1495
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1471
1496
|
return false;
|
|
@@ -1570,7 +1595,7 @@ async function* callStreamed(transport, origin, route2, body, token, signal) {
|
|
|
1570
1595
|
}
|
|
1571
1596
|
}
|
|
1572
1597
|
|
|
1573
|
-
// packages/sdk-
|
|
1598
|
+
// packages/sdk-dispatch/dist/module-factory.js
|
|
1574
1599
|
function freezeDoc(doc2) {
|
|
1575
1600
|
return Object.freeze({ does: doc2.does, refuses: Object.freeze([...doc2.refuses]) });
|
|
1576
1601
|
}
|
|
@@ -1607,7 +1632,7 @@ function createModuleFactory(entries6, transport, origin, token) {
|
|
|
1607
1632
|
return Object.freeze(Object.fromEntries(Object.entries(byCapability).map(([capability, methods]) => [capability, Object.freeze(methods)])));
|
|
1608
1633
|
}
|
|
1609
1634
|
|
|
1610
|
-
// packages/sdk-
|
|
1635
|
+
// packages/sdk-dispatch/dist/typed-client.js
|
|
1611
1636
|
function createTypedClient(names, entries6, transport, origin, token) {
|
|
1612
1637
|
const factory = createModuleFactory(entries6, transport, origin, token);
|
|
1613
1638
|
const byName = new Map(entries6.map((entry2) => [entry2.name, entry2]));
|
|
@@ -1626,7 +1651,7 @@ function createTypedClient(names, entries6, transport, origin, token) {
|
|
|
1626
1651
|
return Object.freeze(client);
|
|
1627
1652
|
}
|
|
1628
1653
|
|
|
1629
|
-
// packages/sdk-
|
|
1654
|
+
// packages/sdk-dispatch/dist/https-transport.js
|
|
1630
1655
|
import { request as request2 } from "node:https";
|
|
1631
1656
|
function createHttpsTransport(origin, options = {}, deadlineMs = REQUEST_DEADLINE_MS) {
|
|
1632
1657
|
const originUrl = new URL(origin);
|
|
@@ -1698,7 +1723,7 @@ function createHttpsTransport(origin, options = {}, deadlineMs = REQUEST_DEADLIN
|
|
|
1698
1723
|
};
|
|
1699
1724
|
}
|
|
1700
1725
|
|
|
1701
|
-
// packages/sdk-
|
|
1726
|
+
// packages/sdk-dispatch/dist/token-routes.js
|
|
1702
1727
|
async function redeem(transport, origin, body) {
|
|
1703
1728
|
return call(transport, origin, "redeem", body, null, null);
|
|
1704
1729
|
}
|
|
@@ -1887,6 +1912,9 @@ function exploreViewAddress(address, state) {
|
|
|
1887
1912
|
const split = subject.indexOf("?");
|
|
1888
1913
|
const path = split === -1 ? subject : subject.slice(0, split);
|
|
1889
1914
|
const query2 = new URLSearchParams(split === -1 ? "" : subject.slice(split + 1));
|
|
1915
|
+
if (state.setId !== void 0 && state.setId !== null && state.setId.length > 0) {
|
|
1916
|
+
query2.set("set", state.setId);
|
|
1917
|
+
}
|
|
1890
1918
|
if (state.typeKey !== null) {
|
|
1891
1919
|
query2.set("type", state.typeKey);
|
|
1892
1920
|
}
|
|
@@ -2021,6 +2049,11 @@ function linkPath(organisationId, projectId, subject, ref) {
|
|
|
2021
2049
|
// packages/objects-sdk/dist/transport-client.js
|
|
2022
2050
|
var OBJECTS_ROUTE_ENTRIES = routeEntriesOf("objects-sdk");
|
|
2023
2051
|
var OBJECTS_ROUTE_NAMES = [
|
|
2052
|
+
"createObjectSet",
|
|
2053
|
+
"listObjectSets",
|
|
2054
|
+
"readObjectSet",
|
|
2055
|
+
"updateObjectSet",
|
|
2056
|
+
"deleteObjectSet",
|
|
2024
2057
|
"readObject",
|
|
2025
2058
|
"queryObjects",
|
|
2026
2059
|
"aggregateObjects",
|
|
@@ -8531,7 +8564,7 @@ var typesIcons = {
|
|
|
8531
8564
|
}
|
|
8532
8565
|
};
|
|
8533
8566
|
|
|
8534
|
-
// packages/demo-
|
|
8567
|
+
// packages/demo-player/dist/definition.js
|
|
8535
8568
|
var STRING = { kind: "string" };
|
|
8536
8569
|
var NUMBER = { kind: "number" };
|
|
8537
8570
|
var PERSON = { kind: "person" };
|
|
@@ -8846,7 +8879,7 @@ function worldSteps(size, ownerPersonId, data) {
|
|
|
8846
8879
|
}
|
|
8847
8880
|
var DEMO_TYPE_VERSION = 1;
|
|
8848
8881
|
|
|
8849
|
-
// packages/demo-
|
|
8882
|
+
// packages/demo-player/dist/ocgt-world.js
|
|
8850
8883
|
var SYSTEM_TREE = [
|
|
8851
8884
|
{ identifier: "OCGT", name: "Open Cycle Gas Turbine Plant", parent: null },
|
|
8852
8885
|
{ identifier: "GT", name: "Gas Turbine", parent: "OCGT" },
|
|
@@ -9071,7 +9104,7 @@ var OCGT_WORLD = {
|
|
|
9071
9104
|
})
|
|
9072
9105
|
};
|
|
9073
9106
|
|
|
9074
|
-
// packages/demo-
|
|
9107
|
+
// packages/demo-player/dist/player.js
|
|
9075
9108
|
var TRUNK_REF = "main";
|
|
9076
9109
|
var IDEMPOTENCY_PREFIX = "demo-seed";
|
|
9077
9110
|
var DemoRouteRefusedError = class extends Error {
|
|
@@ -9701,12 +9734,13 @@ var IDENTIFIER_FIELD = Object.freeze({
|
|
|
9701
9734
|
"app-draft": "appKey"
|
|
9702
9735
|
});
|
|
9703
9736
|
var PROJECT_REF_USAGE = "openeng link <explore|branch-diff|project> --project <id> --ref <ref>";
|
|
9737
|
+
var SET_USAGE = "openeng link explore --project <id> --ref <ref> --object-set <id>";
|
|
9704
9738
|
var REF_USAGE = "openeng link <ontology|change-set> --ref <ref>";
|
|
9705
9739
|
var DRAFT_USAGE = "openeng link app-draft <appKey> --ref <ref>";
|
|
9706
9740
|
var IDENTIFIED_USAGE = "openeng link <object|type|proposal|app> <identifier> --project <id> --ref <ref>";
|
|
9707
9741
|
var APP_PAGE_USAGE = "openeng link app-page <appKey> <pageKey> --project <id> --ref <ref>";
|
|
9708
9742
|
var PAGE_USAGE = "openeng link organisation-page <page>";
|
|
9709
|
-
var LINK_HELP = [PROJECT_REF_USAGE, REF_USAGE, DRAFT_USAGE, IDENTIFIED_USAGE, APP_PAGE_USAGE, PAGE_USAGE];
|
|
9743
|
+
var LINK_HELP = [PROJECT_REF_USAGE, SET_USAGE, REF_USAGE, DRAFT_USAGE, IDENTIFIED_USAGE, APP_PAGE_USAGE, PAGE_USAGE];
|
|
9710
9744
|
var refusal = (message) => ({ kind: "client-refusal", message });
|
|
9711
9745
|
var SCOPE_OF_KIND = Object.freeze({
|
|
9712
9746
|
object: "project-and-ref",
|
|
@@ -9837,12 +9871,21 @@ async function link(context) {
|
|
|
9837
9871
|
if (typeof scope === "string") {
|
|
9838
9872
|
return refusal(`openeng link ${subject.kind} ${scope}`);
|
|
9839
9873
|
}
|
|
9840
|
-
|
|
9874
|
+
if (options.objectSet !== void 0 && (subject.kind !== "explore" || options.objectSet.length === 0)) {
|
|
9875
|
+
return refusal("--object-set needs a saved set identifier and the explore page");
|
|
9876
|
+
}
|
|
9877
|
+
const objectSet = options.objectSet;
|
|
9878
|
+
const path = options.objectSet === void 0 ? linkPath(organisation.id, scope.project, subject, scope.ref) : exploreViewAddress({ organisationId: organisation.id, projectId: scope.project, ref: scope.ref, q: null }, { typeKey: null, objectId: null, setId: options.objectSet });
|
|
9841
9879
|
const run2 = await runAuthenticated(host, deps, async (clients) => {
|
|
9842
|
-
const [origin, checks] = await Promise.all([
|
|
9880
|
+
const [origin, checks, saved] = await Promise.all([
|
|
9843
9881
|
clients.admin.readWebOrigin({ input: {} }),
|
|
9844
|
-
Promise.all(subjectReads(clients, subject, scope))
|
|
9882
|
+
Promise.all(subjectReads(clients, subject, scope)),
|
|
9883
|
+
objectSet === void 0 ? Promise.resolve(null) : clients.objects.readObjectSet({
|
|
9884
|
+
selector: { projectId: scope.project, ref: scope.ref },
|
|
9885
|
+
input: { setId: objectSet }
|
|
9886
|
+
})
|
|
9845
9887
|
]);
|
|
9888
|
+
if (saved !== null && ("refusal" in saved || saved.replayed === true)) return saved;
|
|
9846
9889
|
const blocked = checks.find((check) => check.missing === null && ("refusal" in check.answer || check.answer.replayed === true));
|
|
9847
9890
|
if (blocked !== void 0) return blocked.answer;
|
|
9848
9891
|
if ("refusal" in origin) {
|
|
@@ -10876,6 +10919,7 @@ import { parseArgs } from "node:util";
|
|
|
10876
10919
|
|
|
10877
10920
|
// packages/cli/src/cli-options.ts
|
|
10878
10921
|
var CLI_OPTIONS = {
|
|
10922
|
+
"object-set": { type: "string" },
|
|
10879
10923
|
host: { type: "string" },
|
|
10880
10924
|
"sign-in-origin": { type: "string" },
|
|
10881
10925
|
json: { type: "boolean" },
|
|
@@ -10912,7 +10956,7 @@ var CLI_OPTIONS = {
|
|
|
10912
10956
|
};
|
|
10913
10957
|
|
|
10914
10958
|
// packages/cli/src/cli-version.ts
|
|
10915
|
-
var PATCH_VERSION =
|
|
10959
|
+
var PATCH_VERSION = 0;
|
|
10916
10960
|
var CLI_VERSION = `0.${PROTOCOL_VERSION}.${PATCH_VERSION}`;
|
|
10917
10961
|
|
|
10918
10962
|
// packages/cli/src/environment.ts
|
|
@@ -11026,6 +11070,7 @@ function parseInvocation(argv) {
|
|
|
11026
11070
|
json: values.json === true,
|
|
11027
11071
|
open: values["no-open"] !== true,
|
|
11028
11072
|
project: values.project,
|
|
11073
|
+
objectSet: values["object-set"],
|
|
11029
11074
|
organisation: values.organisation === true,
|
|
11030
11075
|
readOnly: values["read-only"] === true,
|
|
11031
11076
|
object: values.object,
|
package/package.json
CHANGED
package/skill/demo/SKILL.md
CHANGED
|
@@ -1,112 +1,139 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: demo
|
|
3
|
-
description: Use when a person new to OpenEngineering wants a hands-on tour, or has just signed in and has no task of their own yet.
|
|
3
|
+
description: Use when a person new to OpenEngineering wants a hands-on tour, or has just signed in and has no task of their own yet. Offers the example plant seed, a free-form capability tour around their workflow, or a task they name.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Give a person a tour of OpenEngineering
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
8
|
+
## 1. Offer three paths
|
|
9
|
+
|
|
10
|
+
After sign-in, when the person has no task of their own, offer once:
|
|
11
|
+
|
|
12
|
+
- **Seed demo**: create a project, run `openeng demo seed --project <id>`, then follow the
|
|
13
|
+
[Quickstart](https://docs.openeng.io/get-started/quickstart/) together.
|
|
14
|
+
- **Free-form tour** (the main path): build a small example around their work and explore its
|
|
15
|
+
capabilities together in the app.
|
|
16
|
+
- **Something else**: follow the task the person names. They may decline the tour.
|
|
17
|
+
|
|
18
|
+
Before the tour starts, load every capability below into your own native task or plan tool,
|
|
19
|
+
whatever your harness provides: one item per capability, its Checklist line as the title and its
|
|
20
|
+
Features shown line as the detail. Show the person the list and say they may skip any item.
|
|
21
|
+
Run one item at a time. Tick it only when the person has seen its result in the app and you have
|
|
22
|
+
checked that result with a read. Drop a declined item from the remaining work and mark it skipped,
|
|
23
|
+
never done. If you have no task or plan tool, write the same checklist in the conversation and
|
|
24
|
+
show each item's state again whenever it changes.
|
|
25
|
+
|
|
26
|
+
Offer C1, C3 and C5 first, then the others by the person's interest. Use the chosen playbook or
|
|
27
|
+
the example plant for the stories. All capabilities below are shipped. Leave per-field conflicts
|
|
28
|
+
out of every story.
|
|
29
|
+
|
|
30
|
+
- [ ] C1. Describe your workflow, and use the tool five minutes later
|
|
31
|
+
Checklist: Build a working tool from a description of the person's workflow.
|
|
32
|
+
Features shown: Organisations and projects; Familiar workflow playbooks; Types and the ontology;
|
|
33
|
+
Ontology agent; Rail groups and type icons; Objects; Table of one type; The object card.
|
|
34
|
+
|
|
35
|
+
- [ ] C2. One data model, two ways of working: a CRUD app or a branch-first engineering workflow
|
|
36
|
+
Checklist: Switch one project between direct edits on `main` and branch-only edits.
|
|
37
|
+
Features shown: Objects; Branches; Branch diff and changed-object accents; Proposals; Roles and
|
|
38
|
+
membership; Ref rules.
|
|
39
|
+
|
|
40
|
+
- [ ] C3. Follow one question across every tool
|
|
41
|
+
Checklist: Answer one question that crosses requirements, parts and tests.
|
|
42
|
+
Features shown: Relationships; Structure tree; Graph and Explore; Paths between two objects;
|
|
43
|
+
Counts and rollups; The object card.
|
|
44
|
+
|
|
45
|
+
- [ ] C4. Every record carries its own story
|
|
46
|
+
Checklist: Show who changed a record, why, and what a delete would take with it.
|
|
47
|
+
Features shown: The object card; Object history with per-field attribution; Comments and
|
|
48
|
+
subscribers; Delete preview; Branch history and the audit trail.
|
|
49
|
+
|
|
50
|
+
- [ ] C5. An agent does the work, a person makes the call
|
|
51
|
+
Checklist: Have the in-product agent make a change that a person approves and merges.
|
|
52
|
+
Features shown: Branches; Branch diff and changed-object accents; Proposals; Branch history and
|
|
53
|
+
the audit trail; Object agent; Agent model per organisation; Agent ceiling.
|
|
54
|
+
|
|
55
|
+
- [ ] C6. Freeze what shipped, keep building what comes next
|
|
56
|
+
Checklist: Freeze a released part and keep a read-only release baseline.
|
|
57
|
+
Features shown: Types and the ontology; Objects; Relationships; Organisation refs; Instance
|
|
58
|
+
locks; Type rules.
|
|
59
|
+
|
|
60
|
+
- [ ] C7. Your CAD system stays the source of truth
|
|
61
|
+
Checklist: Mirror Onshape parts and link a requirement to one of them.
|
|
62
|
+
Features shown: Types and the ontology; Relationships; Service identities; Onshape mirror; Type
|
|
63
|
+
rules.
|
|
64
|
+
|
|
65
|
+
- [ ] C8. Build on it: a screen for each team, and your own app
|
|
66
|
+
Checklist: Build a team page from configuration, then a small OAuth app on the same data.
|
|
67
|
+
Features shown: Counts and rollups; Object views and App views; Apps with several pages; Roles
|
|
68
|
+
and membership; OAuth apps.
|
|
69
|
+
|
|
70
|
+
## 2. Agree the workflow and keep its stop points
|
|
71
|
+
|
|
72
|
+
Ask what the person designs or manages and where the work gets hard. Offer a fitting playbook:
|
|
73
|
+
`openeng skill playbook engineering-requirements`, `product-lifecycle` or `project-management`,
|
|
74
|
+
or use their own vocabulary. Agree a small story with a visible result. Create a demo organisation
|
|
75
|
+
with `openeng org create` unless asked to use an existing one; say which data is invented.
|
|
76
|
+
Ask before touching existing data, inviting anyone, connecting Onshape or registering an app.
|
|
77
|
+
Ask at most two questions at a time; do not turn routine commands into permission questions.
|
|
78
|
+
|
|
79
|
+
Whenever the tour designs types, read `openeng skill new-use-case` and follow every stop point
|
|
80
|
+
in order: show the person the work and wait for agreement at each one. Do not skip a stop point
|
|
81
|
+
to speed up the tour. Read `openeng skill conventions` before choosing relationships, properties,
|
|
82
|
+
icons and rail groups. Draft nothing before new-use-case's drafting step; accept a change set
|
|
83
|
+
only on the person's word naming it.
|
|
84
|
+
|
|
85
|
+
## 3. Show one story at a time
|
|
86
|
+
|
|
87
|
+
Use `openeng help <module> <route>` for request shapes. Each story answers a question the person
|
|
88
|
+
cares about; do not explain a primitive in isolation.
|
|
89
|
+
|
|
90
|
+
- C1: agree and publish types from the chosen playbook, write believable data with
|
|
91
|
+
`objects-sdk mutateBatch`, then show the rail, table and object card with `link type`.
|
|
92
|
+
- C2: edit on main, add a merge-only rule, show the same edit refused `protected`, then branch,
|
|
93
|
+
edit, compare and submit a proposal. The person merges; remove the rule and show direct edits.
|
|
94
|
+
- C3: narrow with `objects-sdk readStructure`, show `link explore`, and answer a question
|
|
95
|
+
across requirements, parts and tests with `queryObjects`, `findPaths` and `aggregateObjects`.
|
|
96
|
+
- C4: open a record's history, comment and subscribe; use `objects-sdk previewDelete` before
|
|
97
|
+
any deletion, and read branch history and `admin-sdk listAudit`.
|
|
98
|
+
- C5: show the organisation's agent model and project's `ceiling show`. The person uses
|
|
99
|
+
"Open agent", approves its plan, inspects the branch diff, submits and merges. Read the audit
|
|
100
|
+
naming the person and run; show the agent refused on protected main.
|
|
101
|
+
- C6: use `locks set --lock frozen` on a released part, show an edit refused, create its successor
|
|
102
|
+
and relationship, and keep a baseline with `org-refs create --read-only`. Show an immutable
|
|
103
|
+
test result refusing changes on a branch too.
|
|
104
|
+
- C7: for an Onshape user, agree the import scope; use `connector create`, `set-credential`,
|
|
105
|
+
`draft-types`, publish agreed types, `run` and `runs`. Link a requirement to a mirrored part,
|
|
106
|
+
show it cannot be edited here, and show a repeat import preserves the requirement.
|
|
107
|
+
- C8: read `openeng skill build-ui` and its component catalogue, publish a team page through
|
|
108
|
+
the App draft workflow, and show `link app`. Offer a small local OAuth app reading the same
|
|
109
|
+
data; show consent and how to disconnect it.
|
|
110
|
+
|
|
111
|
+
At each step, say what comes next and why, make the smallest useful change (one atomic batch
|
|
112
|
+
for related writes), validate before publishing, and read the result in the intended organisation,
|
|
113
|
+
project and ref. Give a link from `openeng link`, say what they should see, and leave time to see it.
|
|
114
|
+
Invite an action that matters, then check its result with a read. Keep accepted, validated,
|
|
115
|
+
published and seen in the app distinct. Drive through the CLI; the person operates the app.
|
|
116
|
+
|
|
117
|
+
The person enters Onshape keys themselves at `openeng connector set-credential`'s prompt;
|
|
118
|
+
never ask for keys in conversation or type them. Mirrored objects are owned by the connector.
|
|
119
|
+
For OAuth, read the published client contract and `openeng help admin-sdk registerClient`.
|
|
120
|
+
Register a public client with a `http://127.0.0.1:<port>/callback` redirect; use authorization code
|
|
121
|
+
with PKCE. Keep the local app read-only unless asked for more; it never sees their password.
|
|
122
|
+
|
|
123
|
+
## 4. Handle refusals and finish
|
|
124
|
+
|
|
125
|
+
Read a refusal and fix the input. If help is insufficient, record one minimal command and answer
|
|
126
|
+
and ask the person; do not guess in a loop. For an unknown outcome, read state before writing again.
|
|
127
|
+
Never claim to have contacted the OpenEngineering team.
|
|
128
|
+
|
|
129
|
+
Recap completed and skipped tasks, return links and next steps. Say what remains: types, objects,
|
|
130
|
+
branches, proposals, drafts and any connector or registered client, and how to revoke the connector
|
|
131
|
+
(`openeng connector revoke`) or disconnect the app. Agree before deleting anything.
|
|
132
|
+
Do not imply a short tour proves every feature or permission.
|
|
105
133
|
|
|
106
134
|
## Dogfood mode (only when the person asks for feedback capture)
|
|
107
135
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
priority and the open questions, kept apart from the recap. Never send feedback anywhere yourself.
|
|
136
|
+
Record friction as it happens: command, answer, confidence, and whether it is your omission, a help
|
|
137
|
+
gap, an observed defect, a user-reported issue, a feature request or an open question. Merge later
|
|
138
|
+
corrections into earlier entries. Hand over one file with evidence, proposed priorities and open
|
|
139
|
+
questions, separate from the recap. Never send feedback anywhere yourself.
|
package/skill/openeng/SKILL.md
CHANGED
|
@@ -263,6 +263,18 @@ project. `openeng link ontology --ref <ref>` and `openeng link change-set --ref
|
|
|
263
263
|
project, and `openeng link organisation-page <page>` takes neither flag. The organisation is the one
|
|
264
264
|
your session is attached to.
|
|
265
265
|
|
|
266
|
+
### Save an object set and link to its canvas
|
|
267
|
+
|
|
268
|
+
1. Run `openeng help objects-sdk createObjectSet` and `openeng help objects-sdk readObjectSet`.
|
|
269
|
+
2. Query the objects you need with `openeng objects-sdk queryObjects --json`. Keep each object's
|
|
270
|
+
project with its identifier; one set may contain objects of several projects in your organisation.
|
|
271
|
+
3. Call `openeng objects-sdk createObjectSet` with a name and the selected addresses, following its
|
|
272
|
+
help. Keep the returned set identifier and revision. Retrying with the same idempotency key
|
|
273
|
+
returns that original answer.
|
|
274
|
+
4. Run `openeng link explore --project <page project> --ref <ref> --object-set <set id>` and give the
|
|
275
|
+
person the address it prints. It reads the set first; a refused read prints no link. The set
|
|
276
|
+
stores no ref, so the link's ref chooses which version of its objects opens.
|
|
277
|
+
|
|
266
278
|
Every kind with `--ref`, including `ontology` and `change-set`, takes `main` or
|
|
267
279
|
`<projectId>/<branch>`, the ref the platform returns. A bare branch name or change-set id is
|
|
268
280
|
refused by `openeng link`. Before printing, the command reads the ref and the page's own subject;
|