@craftspace/cli 0.4.3 → 0.6.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/dist/index.js +459 -291
- package/dist/machine.d.ts +1 -1
- package/dist/machine.js +112 -22
- package/dist/probe.d.ts +0 -1
- package/dist/probe.js +3 -66
- package/dist/run.d.ts +2 -1
- package/dist/run.js +2 -2
- package/dist/setup.d.ts +9 -5
- package/dist/setup.js +91 -80
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4632,8 +4632,8 @@ var BIGINT_FORMAT_RANGES = {
|
|
|
4632
4632
|
};
|
|
4633
4633
|
function pick(schema, mask) {
|
|
4634
4634
|
const currDef = schema._zod.def;
|
|
4635
|
-
const
|
|
4636
|
-
const hasChecks =
|
|
4635
|
+
const checks2 = currDef.checks;
|
|
4636
|
+
const hasChecks = checks2 && checks2.length > 0;
|
|
4637
4637
|
if (hasChecks) {
|
|
4638
4638
|
throw new Error(".pick() cannot be used on object schemas containing refinements");
|
|
4639
4639
|
}
|
|
@@ -4657,8 +4657,8 @@ function pick(schema, mask) {
|
|
|
4657
4657
|
}
|
|
4658
4658
|
function omit(schema, mask) {
|
|
4659
4659
|
const currDef = schema._zod.def;
|
|
4660
|
-
const
|
|
4661
|
-
const hasChecks =
|
|
4660
|
+
const checks2 = currDef.checks;
|
|
4661
|
+
const hasChecks = checks2 && checks2.length > 0;
|
|
4662
4662
|
if (hasChecks) {
|
|
4663
4663
|
throw new Error(".omit() cannot be used on object schemas containing refinements");
|
|
4664
4664
|
}
|
|
@@ -4684,8 +4684,8 @@ function extend(schema, shape) {
|
|
|
4684
4684
|
if (!isPlainObject(shape)) {
|
|
4685
4685
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
4686
4686
|
}
|
|
4687
|
-
const
|
|
4688
|
-
const hasChecks =
|
|
4687
|
+
const checks2 = schema._zod.def.checks;
|
|
4688
|
+
const hasChecks = checks2 && checks2.length > 0;
|
|
4689
4689
|
if (hasChecks) {
|
|
4690
4690
|
const existingShape = schema._zod.def.shape;
|
|
4691
4691
|
for (const key in shape) {
|
|
@@ -4735,8 +4735,8 @@ function merge(a, b) {
|
|
|
4735
4735
|
}
|
|
4736
4736
|
function partial(Class2, schema, mask) {
|
|
4737
4737
|
const currDef = schema._zod.def;
|
|
4738
|
-
const
|
|
4739
|
-
const hasChecks =
|
|
4738
|
+
const checks2 = currDef.checks;
|
|
4739
|
+
const hasChecks = checks2 && checks2.length > 0;
|
|
4740
4740
|
if (hasChecks) {
|
|
4741
4741
|
throw new Error(".partial() cannot be used on object schemas containing refinements");
|
|
4742
4742
|
}
|
|
@@ -5238,10 +5238,10 @@ var nanoid = /^[a-zA-Z0-9_-]{21}$/;
|
|
|
5238
5238
|
var duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
|
5239
5239
|
var extendedDuration = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
|
|
5240
5240
|
var guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
5241
|
-
var uuid = (
|
|
5242
|
-
if (!
|
|
5241
|
+
var uuid = (version2) => {
|
|
5242
|
+
if (!version2)
|
|
5243
5243
|
return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
|
5244
|
-
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${
|
|
5244
|
+
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version2}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
|
|
5245
5245
|
};
|
|
5246
5246
|
var uuid4 = /* @__PURE__ */ uuid(4);
|
|
5247
5247
|
var uuid6 = /* @__PURE__ */ uuid(6);
|
|
@@ -5923,25 +5923,25 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
5923
5923
|
inst._zod.def = def;
|
|
5924
5924
|
inst._zod.bag = inst._zod.bag || {};
|
|
5925
5925
|
inst._zod.version = version;
|
|
5926
|
-
const
|
|
5926
|
+
const checks2 = [...inst._zod.def.checks ?? []];
|
|
5927
5927
|
if (inst._zod.traits.has("$ZodCheck")) {
|
|
5928
|
-
|
|
5928
|
+
checks2.unshift(inst);
|
|
5929
5929
|
}
|
|
5930
|
-
for (const ch of
|
|
5930
|
+
for (const ch of checks2) {
|
|
5931
5931
|
for (const fn of ch._zod.onattach) {
|
|
5932
5932
|
fn(inst);
|
|
5933
5933
|
}
|
|
5934
5934
|
}
|
|
5935
|
-
if (
|
|
5935
|
+
if (checks2.length === 0) {
|
|
5936
5936
|
(_a3 = inst._zod).deferred ?? (_a3.deferred = []);
|
|
5937
5937
|
inst._zod.deferred?.push(() => {
|
|
5938
5938
|
inst._zod.run = inst._zod.parse;
|
|
5939
5939
|
});
|
|
5940
5940
|
} else {
|
|
5941
|
-
const runChecks = (payload,
|
|
5941
|
+
const runChecks = (payload, checks3, ctx) => {
|
|
5942
5942
|
let isAborted = aborted(payload);
|
|
5943
5943
|
let asyncResult;
|
|
5944
|
-
for (const ch of
|
|
5944
|
+
for (const ch of checks3) {
|
|
5945
5945
|
if (ch._zod.def.when) {
|
|
5946
5946
|
if (explicitlyAborted(payload))
|
|
5947
5947
|
continue;
|
|
@@ -5985,7 +5985,7 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
5985
5985
|
canary.aborted = true;
|
|
5986
5986
|
return canary;
|
|
5987
5987
|
}
|
|
5988
|
-
const checkResult = runChecks(payload,
|
|
5988
|
+
const checkResult = runChecks(payload, checks2, ctx);
|
|
5989
5989
|
if (checkResult instanceof Promise) {
|
|
5990
5990
|
if (ctx.async === false)
|
|
5991
5991
|
throw new $ZodAsyncError();
|
|
@@ -6010,9 +6010,9 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
6010
6010
|
if (result instanceof Promise) {
|
|
6011
6011
|
if (ctx.async === false)
|
|
6012
6012
|
throw new $ZodAsyncError();
|
|
6013
|
-
return result.then((result2) => runChecks(result2,
|
|
6013
|
+
return result.then((result2) => runChecks(result2, checks2, ctx));
|
|
6014
6014
|
}
|
|
6015
|
-
return runChecks(result,
|
|
6015
|
+
return runChecks(result, checks2, ctx);
|
|
6016
6016
|
};
|
|
6017
6017
|
}
|
|
6018
6018
|
defineLazy(inst, "~standard", () => ({
|
|
@@ -18117,10 +18117,10 @@ function fromJSONSchema(schema, params) {
|
|
|
18117
18117
|
} catch {
|
|
18118
18118
|
throw new Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas");
|
|
18119
18119
|
}
|
|
18120
|
-
const
|
|
18120
|
+
const version2 = detectVersion(normalized, params?.defaultTarget);
|
|
18121
18121
|
const defs = normalized.$defs || normalized.definitions || {};
|
|
18122
18122
|
const ctx = {
|
|
18123
|
-
version:
|
|
18123
|
+
version: version2,
|
|
18124
18124
|
defs,
|
|
18125
18125
|
refs: /* @__PURE__ */ new Map(),
|
|
18126
18126
|
processing: /* @__PURE__ */ new Set(),
|
|
@@ -18710,6 +18710,16 @@ var GUS_MODELS = [
|
|
|
18710
18710
|
reasoning: true,
|
|
18711
18711
|
harness: GusHarness.OpenCode
|
|
18712
18712
|
},
|
|
18713
|
+
{
|
|
18714
|
+
id: "deepseek/deepseek-v4.1-flash",
|
|
18715
|
+
label: "DeepSeek V4.1 Flash",
|
|
18716
|
+
blurb: "The V4 Flash refresh. Same pennies, steadier across a long tool run.",
|
|
18717
|
+
inputUsdPerMillion: 0.08,
|
|
18718
|
+
outputUsdPerMillion: 0.18,
|
|
18719
|
+
contextWindow: 1048576,
|
|
18720
|
+
reasoning: true,
|
|
18721
|
+
harness: GusHarness.OpenCode
|
|
18722
|
+
},
|
|
18713
18723
|
{
|
|
18714
18724
|
id: "deepseek/deepseek-v4-pro-0813",
|
|
18715
18725
|
label: "DeepSeek V4 Pro",
|
|
@@ -18778,6 +18788,18 @@ var AuditActor;
|
|
|
18778
18788
|
AuditActor2["System"] = "system";
|
|
18779
18789
|
AuditActor2["Anonymous"] = "anonymous";
|
|
18780
18790
|
})(AuditActor || (AuditActor = {}));
|
|
18791
|
+
var AuditResource;
|
|
18792
|
+
(function(AuditResource2) {
|
|
18793
|
+
AuditResource2["Members"] = "members";
|
|
18794
|
+
AuditResource2["Connections"] = "connections";
|
|
18795
|
+
AuditResource2["Pages"] = "pages";
|
|
18796
|
+
AuditResource2["Spaces"] = "spaces";
|
|
18797
|
+
AuditResource2["Tables"] = "tables";
|
|
18798
|
+
AuditResource2["Agents"] = "agents";
|
|
18799
|
+
AuditResource2["Automation"] = "automation";
|
|
18800
|
+
AuditResource2["Organization"] = "organization";
|
|
18801
|
+
AuditResource2["Tools"] = "tools";
|
|
18802
|
+
})(AuditResource || (AuditResource = {}));
|
|
18781
18803
|
var AuditTier;
|
|
18782
18804
|
(function(AuditTier2) {
|
|
18783
18805
|
AuditTier2["Critical"] = "critical";
|
|
@@ -18890,7 +18912,8 @@ var AUDIT_RETENTION_DAYS = {
|
|
|
18890
18912
|
};
|
|
18891
18913
|
var AUDIT_GROUPS = [
|
|
18892
18914
|
{
|
|
18893
|
-
|
|
18915
|
+
resource: AuditResource.Members,
|
|
18916
|
+
label: "Members and tokens",
|
|
18894
18917
|
actions: [
|
|
18895
18918
|
AuditAction.AccessDenied,
|
|
18896
18919
|
AuditAction.MemberSignedIn,
|
|
@@ -18904,7 +18927,8 @@ var AUDIT_GROUPS = [
|
|
|
18904
18927
|
]
|
|
18905
18928
|
},
|
|
18906
18929
|
{
|
|
18907
|
-
|
|
18930
|
+
resource: AuditResource.Connections,
|
|
18931
|
+
label: "Connected apps",
|
|
18908
18932
|
actions: [
|
|
18909
18933
|
AuditAction.ConnectionCreated,
|
|
18910
18934
|
AuditAction.ConnectionReconnected,
|
|
@@ -18916,23 +18940,34 @@ var AUDIT_GROUPS = [
|
|
|
18916
18940
|
]
|
|
18917
18941
|
},
|
|
18918
18942
|
{
|
|
18919
|
-
|
|
18943
|
+
resource: AuditResource.Pages,
|
|
18944
|
+
label: "Pages",
|
|
18920
18945
|
actions: [
|
|
18921
18946
|
AuditAction.PageCreated,
|
|
18922
18947
|
AuditAction.PageUpdated,
|
|
18923
18948
|
AuditAction.PageDeleted,
|
|
18924
18949
|
AuditAction.PageMoved,
|
|
18925
18950
|
AuditAction.PageShared,
|
|
18926
|
-
AuditAction.PageUnshared
|
|
18951
|
+
AuditAction.PageUnshared
|
|
18952
|
+
]
|
|
18953
|
+
},
|
|
18954
|
+
{
|
|
18955
|
+
resource: AuditResource.Spaces,
|
|
18956
|
+
label: "Spaces",
|
|
18957
|
+
actions: [
|
|
18927
18958
|
AuditAction.SpaceCreated,
|
|
18928
18959
|
AuditAction.SpaceRenamed,
|
|
18929
18960
|
AuditAction.SpaceDeleted,
|
|
18930
|
-
AuditAction.SpaceAccessChanged
|
|
18931
|
-
AuditAction.TableCreated,
|
|
18932
|
-
AuditAction.TableDeleted
|
|
18961
|
+
AuditAction.SpaceAccessChanged
|
|
18933
18962
|
]
|
|
18934
18963
|
},
|
|
18935
18964
|
{
|
|
18965
|
+
resource: AuditResource.Tables,
|
|
18966
|
+
label: "Tables",
|
|
18967
|
+
actions: [AuditAction.TableCreated, AuditAction.TableDeleted]
|
|
18968
|
+
},
|
|
18969
|
+
{
|
|
18970
|
+
resource: AuditResource.Agents,
|
|
18936
18971
|
label: "Agents and channels",
|
|
18937
18972
|
actions: [
|
|
18938
18973
|
AuditAction.AgentCreated,
|
|
@@ -18943,7 +18978,8 @@ var AUDIT_GROUPS = [
|
|
|
18943
18978
|
]
|
|
18944
18979
|
},
|
|
18945
18980
|
{
|
|
18946
|
-
|
|
18981
|
+
resource: AuditResource.Automation,
|
|
18982
|
+
label: "Workflows and kits",
|
|
18947
18983
|
actions: [
|
|
18948
18984
|
AuditAction.KitInstalled,
|
|
18949
18985
|
AuditAction.KitRemoved,
|
|
@@ -18954,10 +18990,7 @@ var AUDIT_GROUPS = [
|
|
|
18954
18990
|
]
|
|
18955
18991
|
},
|
|
18956
18992
|
{
|
|
18957
|
-
|
|
18958
|
-
actions: [AuditAction.McpToolCall, AuditAction.McpRequest]
|
|
18959
|
-
},
|
|
18960
|
-
{
|
|
18993
|
+
resource: AuditResource.Organization,
|
|
18961
18994
|
label: "Organization",
|
|
18962
18995
|
actions: [
|
|
18963
18996
|
AuditAction.OrganizationRenamed,
|
|
@@ -18965,10 +18998,17 @@ var AUDIT_GROUPS = [
|
|
|
18965
18998
|
AuditAction.OrganizationModelChanged,
|
|
18966
18999
|
AuditAction.OrganizationDeleted
|
|
18967
19000
|
]
|
|
19001
|
+
},
|
|
19002
|
+
{
|
|
19003
|
+
resource: AuditResource.Tools,
|
|
19004
|
+
label: "Tool and MCP calls",
|
|
19005
|
+
actions: [AuditAction.McpToolCall, AuditAction.McpRequest]
|
|
18968
19006
|
}
|
|
18969
19007
|
];
|
|
19008
|
+
var AUDIT_RESOURCES = Object.fromEntries(AUDIT_GROUPS.flatMap((group) => group.actions.map((action) => [action, group.resource])));
|
|
18970
19009
|
var AUDIT_LISTED_ACTIONS = AUDIT_GROUPS.flatMap((group) => group.actions);
|
|
18971
|
-
var
|
|
19010
|
+
var AUDIT_QUIET_ACTIONS = [AuditAction.McpRequest, AuditAction.PageRead, AuditAction.PageWrite];
|
|
19011
|
+
var AUDIT_DEFAULT_ACTIONS = AUDIT_LISTED_ACTIONS.filter((action) => !AUDIT_QUIET_ACTIONS.includes(action));
|
|
18972
19012
|
var AUDIT_LABELS = {
|
|
18973
19013
|
[AuditAction.AccessDenied]: "Denied request",
|
|
18974
19014
|
[AuditAction.MemberSignedIn]: "Signed in",
|
|
@@ -19018,6 +19058,11 @@ var AUDIT_LABELS = {
|
|
|
19018
19058
|
[AuditAction.PageRead]: "Read page",
|
|
19019
19059
|
[AuditAction.PageWrite]: "Wrote page"
|
|
19020
19060
|
};
|
|
19061
|
+
var AuditAppSchema = external_exports.object({
|
|
19062
|
+
kind: external_exports.string(),
|
|
19063
|
+
id: external_exports.string().optional(),
|
|
19064
|
+
name: external_exports.string().optional()
|
|
19065
|
+
});
|
|
19021
19066
|
var AuditTargetSchema = external_exports.object({
|
|
19022
19067
|
type: external_exports.string(),
|
|
19023
19068
|
id: external_exports.string().optional(),
|
|
@@ -19035,6 +19080,8 @@ var AuditEntrySchema = external_exports.object({
|
|
|
19035
19080
|
image: external_exports.string().optional()
|
|
19036
19081
|
}),
|
|
19037
19082
|
target: AuditTargetSchema.optional(),
|
|
19083
|
+
app: AuditAppSchema.optional(),
|
|
19084
|
+
outcome: external_exports.enum(["ok", "error"]).optional(),
|
|
19038
19085
|
data: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
19039
19086
|
ip: external_exports.string().optional(),
|
|
19040
19087
|
userAgent: external_exports.string().optional(),
|
|
@@ -19049,15 +19096,38 @@ var AuditSummarySchema = external_exports.object({
|
|
|
19049
19096
|
var AuditQuerySchema = external_exports.object({
|
|
19050
19097
|
days: external_exports.coerce.number().int().refine((value) => AUDIT_RANGES.includes(value)).default(AUDIT_DEFAULT_DAYS),
|
|
19051
19098
|
page: external_exports.coerce.number().int().min(1).default(1),
|
|
19052
|
-
action:
|
|
19099
|
+
action: manyOf(external_exports.enum(AuditAction)),
|
|
19053
19100
|
actor: external_exports.enum(AuditActor).optional(),
|
|
19054
|
-
|
|
19101
|
+
account: manyOf(external_exports.string()),
|
|
19102
|
+
app: manyOf(external_exports.string())
|
|
19103
|
+
});
|
|
19104
|
+
var AuditFacetsSchema = external_exports.object({
|
|
19105
|
+
actions: external_exports.record(external_exports.string(), external_exports.number()),
|
|
19106
|
+
accounts: external_exports.array(external_exports.object({
|
|
19107
|
+
accountId: external_exports.string(),
|
|
19108
|
+
name: external_exports.string(),
|
|
19109
|
+
email: external_exports.string().optional(),
|
|
19110
|
+
image: external_exports.string().optional(),
|
|
19111
|
+
count: external_exports.number()
|
|
19112
|
+
})),
|
|
19113
|
+
apps: external_exports.array(external_exports.object({ kind: external_exports.string(), name: external_exports.string().optional(), count: external_exports.number() }))
|
|
19055
19114
|
});
|
|
19056
19115
|
var AuditResponseSchema = external_exports.object({
|
|
19057
19116
|
summary: AuditSummarySchema,
|
|
19058
19117
|
entries: external_exports.array(AuditEntrySchema),
|
|
19118
|
+
facets: AuditFacetsSchema,
|
|
19059
19119
|
total: external_exports.number()
|
|
19060
19120
|
});
|
|
19121
|
+
var VERB_OVERRIDES = {
|
|
19122
|
+
[AuditAction.McpToolCall]: "called",
|
|
19123
|
+
[AuditAction.McpRequest]: "called",
|
|
19124
|
+
[AuditAction.PageRead]: "read",
|
|
19125
|
+
[AuditAction.PageWrite]: "written",
|
|
19126
|
+
[AuditAction.AdminEnteredOrg]: "opened as support"
|
|
19127
|
+
};
|
|
19128
|
+
function manyOf(schema) {
|
|
19129
|
+
return external_exports.union([schema, external_exports.array(schema)]).optional().transform((value) => value === void 0 ? void 0 : Array.isArray(value) ? value : [value]);
|
|
19130
|
+
}
|
|
19061
19131
|
|
|
19062
19132
|
// ../../shared/dist/organization/install-admin.js
|
|
19063
19133
|
var InstallCredentialNameSchema = external_exports.enum([
|
|
@@ -19310,7 +19380,8 @@ var OAuthCallbackQuerySchema = external_exports.object({
|
|
|
19310
19380
|
});
|
|
19311
19381
|
var ListConnectionsResponseSchema = external_exports.object({
|
|
19312
19382
|
connections: external_exports.array(ConnectionSchema),
|
|
19313
|
-
canManage: external_exports.boolean()
|
|
19383
|
+
canManage: external_exports.boolean(),
|
|
19384
|
+
egressIp: external_exports.string()
|
|
19314
19385
|
});
|
|
19315
19386
|
var CONNECTION_CATEGORIES = [
|
|
19316
19387
|
"Sales & support",
|
|
@@ -19751,6 +19822,10 @@ var GUS_MAX_TURN_MS = 45 * 60 * 1e3;
|
|
|
19751
19822
|
// ../../shared/dist/gus/workstation.js
|
|
19752
19823
|
var WORKSTATION_CORES = 2;
|
|
19753
19824
|
var WORKSTATION_RECIPE_MAX_CHARS = 8e3;
|
|
19825
|
+
var WORKSTATION_MAX_STEPS = 20;
|
|
19826
|
+
var WORKSTATION_STEP_NAME_MAX_CHARS = 60;
|
|
19827
|
+
var WORKSTATION_STEP_DETAIL_MAX_CHARS = 600;
|
|
19828
|
+
var WORKSTATION_MAX_REPOS = 20;
|
|
19754
19829
|
var WORKSTATION_ALLOWLIST_MAX_HOSTS = 50;
|
|
19755
19830
|
var WORKSTATION_HOST_MAX_CHARS = 200;
|
|
19756
19831
|
var SANDBOX_BROWSERS_PATH = "/vercel/sandbox/.cache/ms-playwright";
|
|
@@ -19762,14 +19837,53 @@ var WORKSTATION_SPECS = {
|
|
|
19762
19837
|
};
|
|
19763
19838
|
var PLAYWRIGHT_VERSION = "1.49.1";
|
|
19764
19839
|
var WORKSTATION_BASE_RECIPE = [
|
|
19765
|
-
"# Craftspace base
|
|
19840
|
+
"# Craftspace base v3: a headless browser, ready to use.",
|
|
19841
|
+
`export PLAYWRIGHT_BROWSERS_PATH=${SANDBOX_BROWSERS_PATH}`,
|
|
19766
19842
|
"sudo dnf install -y nss nspr atk at-spi2-atk at-spi2-core cups-libs libdrm libxkbcommon \\",
|
|
19767
19843
|
" libXcomposite libXdamage libXrandr libXfixes libXrender mesa-libgbm pango alsa-lib >/dev/null",
|
|
19768
|
-
`
|
|
19844
|
+
`npx --yes playwright@${PLAYWRIGHT_VERSION} install chromium`
|
|
19769
19845
|
].join("\n");
|
|
19770
19846
|
var HostSchema = external_exports.string().trim().min(1).max(WORKSTATION_HOST_MAX_CHARS).regex(/^[A-Za-z0-9*._:-]+$/, "A host is a domain, optionally with a leading *. and a :port.");
|
|
19847
|
+
var WorkstationStepSchema = external_exports.object({
|
|
19848
|
+
id: external_exports.string().min(1).max(64),
|
|
19849
|
+
name: external_exports.string().trim().min(1).max(WORKSTATION_STEP_NAME_MAX_CHARS),
|
|
19850
|
+
script: external_exports.string().max(WORKSTATION_RECIPE_MAX_CHARS)
|
|
19851
|
+
});
|
|
19852
|
+
var WorkstationRepoSchema = external_exports.object({
|
|
19853
|
+
name: external_exports.string().trim().min(3).max(200).regex(/^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/, "A repo is owner/name."),
|
|
19854
|
+
ref: external_exports.string().trim().min(1).max(200)
|
|
19855
|
+
});
|
|
19856
|
+
var WORKSTATION_SEED_STEPS = [
|
|
19857
|
+
{ id: "step_claude_code", name: "Claude Code", script: "npm install -g @anthropic-ai/claude-code" },
|
|
19858
|
+
{ id: "step_codex", name: "Codex", script: "npm install -g @openai/codex" },
|
|
19859
|
+
{
|
|
19860
|
+
id: "step_github_cli",
|
|
19861
|
+
name: "GitHub CLI",
|
|
19862
|
+
script: [
|
|
19863
|
+
"if command -v gh >/dev/null; then exit 0; fi",
|
|
19864
|
+
"if command -v brew >/dev/null; then brew install gh",
|
|
19865
|
+
"elif command -v dnf >/dev/null; then sudo -n dnf install -y gh",
|
|
19866
|
+
"elif command -v apt-get >/dev/null; then sudo -n apt-get install -y gh",
|
|
19867
|
+
'else echo "no package manager here, install the GitHub CLI by hand" >&2; exit 1',
|
|
19868
|
+
"fi"
|
|
19869
|
+
].join("\n")
|
|
19870
|
+
},
|
|
19871
|
+
{
|
|
19872
|
+
id: "step_chrome",
|
|
19873
|
+
name: "Chrome for Playwright",
|
|
19874
|
+
script: `npx --yes playwright@${PLAYWRIGHT_VERSION} install chromium`
|
|
19875
|
+
}
|
|
19876
|
+
];
|
|
19877
|
+
var WorkstationStepResultSchema = external_exports.object({
|
|
19878
|
+
id: external_exports.string().min(1).max(64),
|
|
19879
|
+
name: external_exports.string().max(WORKSTATION_STEP_NAME_MAX_CHARS),
|
|
19880
|
+
ok: external_exports.boolean(),
|
|
19881
|
+
detail: external_exports.string().max(WORKSTATION_STEP_DETAIL_MAX_CHARS),
|
|
19882
|
+
ms: external_exports.number().int().nonnegative()
|
|
19883
|
+
});
|
|
19771
19884
|
var WorkstationSchema = external_exports.object({
|
|
19772
|
-
|
|
19885
|
+
steps: external_exports.array(WorkstationStepSchema),
|
|
19886
|
+
repos: external_exports.array(WorkstationRepoSchema),
|
|
19773
19887
|
allowlist: external_exports.array(external_exports.string()),
|
|
19774
19888
|
templateId: external_exports.string().nullable(),
|
|
19775
19889
|
publicKey: external_exports.string(),
|
|
@@ -19777,13 +19891,14 @@ var WorkstationSchema = external_exports.object({
|
|
|
19777
19891
|
updatedByName: external_exports.string().nullable()
|
|
19778
19892
|
});
|
|
19779
19893
|
var SaveWorkstationBodySchema = external_exports.object({
|
|
19780
|
-
|
|
19894
|
+
steps: external_exports.array(WorkstationStepSchema).max(WORKSTATION_MAX_STEPS),
|
|
19895
|
+
repos: external_exports.array(WorkstationRepoSchema).max(WORKSTATION_MAX_REPOS),
|
|
19781
19896
|
allowlist: external_exports.array(HostSchema).max(WORKSTATION_ALLOWLIST_MAX_HOSTS)
|
|
19782
19897
|
});
|
|
19783
19898
|
var WorkstationResponseSchema = external_exports.object({ workstation: WorkstationSchema });
|
|
19784
19899
|
|
|
19785
19900
|
// ../../shared/dist/machines/machine.js
|
|
19786
|
-
var CLI_VERSION = "0.
|
|
19901
|
+
var CLI_VERSION = "0.6.0";
|
|
19787
19902
|
var CLI_PACKAGE = "@craftspace/cli";
|
|
19788
19903
|
var CLI_INSTALL = `npm i -g ${CLI_PACKAGE}`;
|
|
19789
19904
|
var MACHINE_BEAT_INTERVAL_MS = 15e3;
|
|
@@ -19804,13 +19919,20 @@ var MachineAuthorizedKeySchema = external_exports.object({
|
|
|
19804
19919
|
addedByName: external_exports.string(),
|
|
19805
19920
|
addedAt: external_exports.coerce.date()
|
|
19806
19921
|
});
|
|
19807
|
-
var MACHINE_TOOLS = ["brain", "
|
|
19922
|
+
var MACHINE_TOOLS = ["brain", "ssh"];
|
|
19808
19923
|
var MachineToolIdSchema = external_exports.enum(MACHINE_TOOLS);
|
|
19809
19924
|
var MachineToolSchema = external_exports.object({
|
|
19810
19925
|
id: MachineToolIdSchema,
|
|
19811
19926
|
ok: external_exports.boolean(),
|
|
19812
19927
|
detail: external_exports.string().max(200)
|
|
19813
19928
|
});
|
|
19929
|
+
var MachineRepoSchema = external_exports.object({
|
|
19930
|
+
name: external_exports.string().max(200),
|
|
19931
|
+
ref: external_exports.string().max(200),
|
|
19932
|
+
path: external_exports.string().max(400),
|
|
19933
|
+
ok: external_exports.boolean(),
|
|
19934
|
+
detail: external_exports.string().max(300)
|
|
19935
|
+
});
|
|
19814
19936
|
var MachineSchema = external_exports.object({
|
|
19815
19937
|
id: external_exports.string(),
|
|
19816
19938
|
tokenId: external_exports.string(),
|
|
@@ -19832,6 +19954,10 @@ var MachineSchema = external_exports.object({
|
|
|
19832
19954
|
state: MachineStateSchema,
|
|
19833
19955
|
sessions: external_exports.array(MachineSessionSchema),
|
|
19834
19956
|
tools: external_exports.array(MachineToolSchema),
|
|
19957
|
+
environment: external_exports.array(WorkstationStepResultSchema),
|
|
19958
|
+
templateId: external_exports.string().nullable(),
|
|
19959
|
+
workDir: external_exports.string().nullable(),
|
|
19960
|
+
repos: external_exports.array(MachineRepoSchema),
|
|
19835
19961
|
authorizedKeys: external_exports.array(MachineAuthorizedKeySchema),
|
|
19836
19962
|
lastBeatAt: external_exports.coerce.date().nullable(),
|
|
19837
19963
|
lastAskedAt: external_exports.coerce.date().nullable(),
|
|
@@ -19894,12 +20020,22 @@ var MachineBeatBodySchema = external_exports.object({
|
|
|
19894
20020
|
sessions: external_exports.array(MachineSessionSchema).max(50),
|
|
19895
20021
|
runs: external_exports.array(MachineRunReportSchema).max(20).default([]),
|
|
19896
20022
|
tools: external_exports.array(MachineToolSchema).max(10).default([]),
|
|
20023
|
+
environment: external_exports.array(WorkstationStepResultSchema).max(WORKSTATION_MAX_STEPS).default([]),
|
|
20024
|
+
templateId: external_exports.string().max(64).nullable().default(null),
|
|
20025
|
+
workDir: external_exports.string().max(400).optional(),
|
|
20026
|
+
repos: external_exports.array(MachineRepoSchema).max(WORKSTATION_MAX_REPOS).default([]),
|
|
19897
20027
|
sshUser: external_exports.string().min(1).max(64).optional()
|
|
19898
20028
|
});
|
|
20029
|
+
var MachineEnvironmentSchema = external_exports.object({
|
|
20030
|
+
templateId: external_exports.string().nullable(),
|
|
20031
|
+
steps: external_exports.array(WorkstationStepSchema),
|
|
20032
|
+
repos: external_exports.array(WorkstationRepoSchema).default([])
|
|
20033
|
+
});
|
|
19899
20034
|
var MachineBeatResponseSchema = external_exports.object({
|
|
19900
20035
|
cli: external_exports.object({ version: external_exports.string(), url: external_exports.string(), sha256: external_exports.string() }).nullable(),
|
|
19901
20036
|
work: external_exports.array(MachineWorkSchema),
|
|
19902
|
-
authorizedKeys: external_exports.array(external_exports.string())
|
|
20037
|
+
authorizedKeys: external_exports.array(external_exports.string()),
|
|
20038
|
+
environment: MachineEnvironmentSchema
|
|
19903
20039
|
});
|
|
19904
20040
|
var AddMachineKeyBodySchema = external_exports.object({
|
|
19905
20041
|
key: external_exports.string().min(60).max(4e3),
|
|
@@ -20251,11 +20387,11 @@ var MemberActivityListResponse = external_exports.object({
|
|
|
20251
20387
|
});
|
|
20252
20388
|
|
|
20253
20389
|
// dist/machine.js
|
|
20254
|
-
import { execFile as
|
|
20255
|
-
import { mkdir, readFile as readFile2, readdir, rm, writeFile } from "node:fs/promises";
|
|
20390
|
+
import { execFile as execFile3, spawn as spawn2 } from "node:child_process";
|
|
20391
|
+
import { mkdir as mkdir2, readFile as readFile2, readdir, rm, writeFile } from "node:fs/promises";
|
|
20256
20392
|
import os5 from "node:os";
|
|
20257
20393
|
import path4 from "node:path";
|
|
20258
|
-
import { promisify as
|
|
20394
|
+
import { promisify as promisify2 } from "node:util";
|
|
20259
20395
|
|
|
20260
20396
|
// ../../../node_modules/@inquirer/core/dist/lib/key.js
|
|
20261
20397
|
var keybindings = ["emacs", "vim"];
|
|
@@ -21225,11 +21361,11 @@ function readlineWidth() {
|
|
|
21225
21361
|
|
|
21226
21362
|
// ../../../node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
|
|
21227
21363
|
function usePointerPosition({ active, renderedItems, pageSize, loop }) {
|
|
21228
|
-
const
|
|
21364
|
+
const state2 = useRef({
|
|
21229
21365
|
lastPointer: active,
|
|
21230
21366
|
lastActive: void 0
|
|
21231
21367
|
});
|
|
21232
|
-
const { lastPointer, lastActive } =
|
|
21368
|
+
const { lastPointer, lastActive } = state2.current;
|
|
21233
21369
|
const middle = Math.floor(pageSize / 2);
|
|
21234
21370
|
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
21235
21371
|
const defaultPointerPosition = renderedItems.slice(0, active).reduce((acc, item) => acc + item.length, 0);
|
|
@@ -21269,8 +21405,8 @@ function usePointerPosition({ active, renderedItems, pageSize, loop }) {
|
|
|
21269
21405
|
);
|
|
21270
21406
|
}
|
|
21271
21407
|
}
|
|
21272
|
-
|
|
21273
|
-
|
|
21408
|
+
state2.current.lastPointer = pointer;
|
|
21409
|
+
state2.current.lastActive = active;
|
|
21274
21410
|
return pointer;
|
|
21275
21411
|
}
|
|
21276
21412
|
function usePagination({ items, active, renderItem, pageSize, loop = true }) {
|
|
@@ -22121,9 +22257,50 @@ var dist_default6 = createPrompt((config2, done) => {
|
|
|
22121
22257
|
return `${lines}${cursorHide}`;
|
|
22122
22258
|
});
|
|
22123
22259
|
|
|
22260
|
+
// dist/probe.js
|
|
22261
|
+
import net from "node:net";
|
|
22262
|
+
import { readFile } from "node:fs/promises";
|
|
22263
|
+
import os from "node:os";
|
|
22264
|
+
import path2 from "node:path";
|
|
22265
|
+
var probe = {
|
|
22266
|
+
async tools({ mcpPath = path2.join(os.homedir(), ".mcp.json") } = {}) {
|
|
22267
|
+
return Promise.all([brainWired(mcpPath), sshListening()]);
|
|
22268
|
+
}
|
|
22269
|
+
};
|
|
22270
|
+
async function brainWired(mcpPath) {
|
|
22271
|
+
const raw = await readFile(mcpPath, "utf8").catch(() => null);
|
|
22272
|
+
if (raw === null)
|
|
22273
|
+
return { id: "brain", ok: false, detail: `no ${short(mcpPath)} on this machine` };
|
|
22274
|
+
const parsed = JSON.parse(raw);
|
|
22275
|
+
const servers = parsed?.mcpServers;
|
|
22276
|
+
const wired = servers !== void 0 && servers !== null && "craftspace" in servers;
|
|
22277
|
+
return {
|
|
22278
|
+
id: "brain",
|
|
22279
|
+
ok: wired,
|
|
22280
|
+
detail: wired ? short(mcpPath) : `${short(mcpPath)} has no craftspace entry`
|
|
22281
|
+
};
|
|
22282
|
+
}
|
|
22283
|
+
function sshListening() {
|
|
22284
|
+
return new Promise((resolve) => {
|
|
22285
|
+
const socket = net.connect({ host: "127.0.0.1", port: 22 });
|
|
22286
|
+
const answer = (ok, detail) => {
|
|
22287
|
+
socket.destroy();
|
|
22288
|
+
resolve({ id: "ssh", ok, detail });
|
|
22289
|
+
};
|
|
22290
|
+
socket.setTimeout(SSH_PROBE_TIMEOUT_MS);
|
|
22291
|
+
socket.on("connect", () => answer(true, "sshd is listening on port 22"));
|
|
22292
|
+
socket.on("timeout", () => answer(false, "nothing answered on port 22"));
|
|
22293
|
+
socket.on("error", () => answer(false, "sshd is not running, so nobody can open a terminal here"));
|
|
22294
|
+
});
|
|
22295
|
+
}
|
|
22296
|
+
function short(target) {
|
|
22297
|
+
return target.startsWith(os.homedir()) ? `~${target.slice(os.homedir().length)}` : target;
|
|
22298
|
+
}
|
|
22299
|
+
var SSH_PROBE_TIMEOUT_MS = 1500;
|
|
22300
|
+
|
|
22124
22301
|
// dist/run.js
|
|
22125
22302
|
import { spawn } from "node:child_process";
|
|
22126
|
-
import
|
|
22303
|
+
import os2 from "node:os";
|
|
22127
22304
|
var runner = {
|
|
22128
22305
|
attended(argv) {
|
|
22129
22306
|
return new Promise((resolve) => {
|
|
@@ -22132,7 +22309,7 @@ var runner = {
|
|
|
22132
22309
|
child.on("close", (code) => resolve(code ?? 0));
|
|
22133
22310
|
});
|
|
22134
22311
|
},
|
|
22135
|
-
async unattended({ work, onProgress }) {
|
|
22312
|
+
async unattended({ work, cwd = os2.homedir(), onProgress }) {
|
|
22136
22313
|
const argv = headlessArgv(work);
|
|
22137
22314
|
const raw = argv[0] === "script";
|
|
22138
22315
|
let output = "";
|
|
@@ -22162,7 +22339,7 @@ var runner = {
|
|
|
22162
22339
|
const code = await new Promise((resolve) => {
|
|
22163
22340
|
const child = spawn(argv[0], argv.slice(1), {
|
|
22164
22341
|
stdio: ["ignore", "pipe", "pipe"],
|
|
22165
|
-
cwd
|
|
22342
|
+
cwd,
|
|
22166
22343
|
env: {
|
|
22167
22344
|
...process.env,
|
|
22168
22345
|
TERM: process.env.TERM ?? "xterm-256color",
|
|
@@ -22259,112 +22436,10 @@ function parseJson(line) {
|
|
|
22259
22436
|
}
|
|
22260
22437
|
|
|
22261
22438
|
// dist/setup.js
|
|
22262
|
-
import { execFile
|
|
22439
|
+
import { execFile } from "node:child_process";
|
|
22440
|
+
import { mkdir } from "node:fs/promises";
|
|
22263
22441
|
import os4 from "node:os";
|
|
22264
22442
|
import path3 from "node:path";
|
|
22265
|
-
import { promisify as promisify2 } from "node:util";
|
|
22266
|
-
|
|
22267
|
-
// dist/probe.js
|
|
22268
|
-
import { execFile } from "node:child_process";
|
|
22269
|
-
import net from "node:net";
|
|
22270
|
-
import { access, readFile } from "node:fs/promises";
|
|
22271
|
-
import os2 from "node:os";
|
|
22272
|
-
import path2 from "node:path";
|
|
22273
|
-
import { promisify } from "node:util";
|
|
22274
|
-
var run = promisify(execFile);
|
|
22275
|
-
var probe = {
|
|
22276
|
-
async tools({ mcpPath = path2.join(os2.homedir(), ".mcp.json") } = {}) {
|
|
22277
|
-
const [brain, claude, codex, git, chrome, ssh] = await Promise.all([
|
|
22278
|
-
brainWired(mcpPath),
|
|
22279
|
-
version2({ id: "claude", command: "claude" }),
|
|
22280
|
-
version2({ id: "codex", command: "codex" }),
|
|
22281
|
-
gitAndGithub(),
|
|
22282
|
-
chromeInstalled(),
|
|
22283
|
-
sshListening()
|
|
22284
|
-
]);
|
|
22285
|
-
return [brain, claude, codex, git, chrome, ssh];
|
|
22286
|
-
}
|
|
22287
|
-
};
|
|
22288
|
-
async function brainWired(mcpPath) {
|
|
22289
|
-
const raw = await readFile(mcpPath, "utf8").catch(() => null);
|
|
22290
|
-
if (raw === null)
|
|
22291
|
-
return { id: "brain", ok: false, detail: `no ${short(mcpPath)} on this machine` };
|
|
22292
|
-
const parsed = JSON.parse(raw);
|
|
22293
|
-
const servers = parsed?.mcpServers;
|
|
22294
|
-
const wired = servers !== void 0 && servers !== null && "craftspace" in servers;
|
|
22295
|
-
return {
|
|
22296
|
-
id: "brain",
|
|
22297
|
-
ok: wired,
|
|
22298
|
-
detail: wired ? short(mcpPath) : `${short(mcpPath)} has no craftspace entry`
|
|
22299
|
-
};
|
|
22300
|
-
}
|
|
22301
|
-
async function version2({ id, command }) {
|
|
22302
|
-
const found = await firstLine(command, ["--version"]);
|
|
22303
|
-
if (found.ran)
|
|
22304
|
-
return { id, ok: true, detail: found.line };
|
|
22305
|
-
return { id, ok: false, detail: found.why === "absent" ? "not installed" : "installed, but it will not report a version" };
|
|
22306
|
-
}
|
|
22307
|
-
async function gitAndGithub() {
|
|
22308
|
-
const git = await firstLine("git", ["--version"]);
|
|
22309
|
-
if (!git.ran)
|
|
22310
|
-
return { id: "git", ok: false, detail: "git is not installed" };
|
|
22311
|
-
const gh = await firstLine("gh", ["--version"]);
|
|
22312
|
-
if (!gh.ran)
|
|
22313
|
-
return { id: "git", ok: false, detail: `${git.line} \xB7 the GitHub CLI is not installed yet` };
|
|
22314
|
-
const account = await githubAccount();
|
|
22315
|
-
return {
|
|
22316
|
-
id: "git",
|
|
22317
|
-
ok: account !== null,
|
|
22318
|
-
detail: account === null ? `${git.line} \xB7 ${gh.line}, run gh auth login on this machine` : `${git.line} \xB7 ${gh.line}, signed in as ${account}`
|
|
22319
|
-
};
|
|
22320
|
-
}
|
|
22321
|
-
async function githubAccount() {
|
|
22322
|
-
const raw = await readFile(path2.join(os2.homedir(), ".config", "gh", "hosts.yml"), "utf8").catch(() => null);
|
|
22323
|
-
return raw === null ? null : githubUser(raw);
|
|
22324
|
-
}
|
|
22325
|
-
function githubUser(hostsYml) {
|
|
22326
|
-
return /^ {4}user: *(\S+) *$/m.exec(hostsYml)?.[1] ?? null;
|
|
22327
|
-
}
|
|
22328
|
-
async function chromeInstalled() {
|
|
22329
|
-
for (const command of [...MAC_CHROME, ...LINUX_CHROME]) {
|
|
22330
|
-
const found = await firstLine(command, ["--version"]);
|
|
22331
|
-
if (found.ran)
|
|
22332
|
-
return { id: "chrome", ok: true, detail: found.line };
|
|
22333
|
-
}
|
|
22334
|
-
return { id: "chrome", ok: false, detail: "not installed yet, so browser runs will fail" };
|
|
22335
|
-
}
|
|
22336
|
-
function sshListening() {
|
|
22337
|
-
return new Promise((resolve) => {
|
|
22338
|
-
const socket = net.connect({ host: "127.0.0.1", port: 22 });
|
|
22339
|
-
const answer = (ok, detail) => {
|
|
22340
|
-
socket.destroy();
|
|
22341
|
-
resolve({ id: "ssh", ok, detail });
|
|
22342
|
-
};
|
|
22343
|
-
socket.setTimeout(SSH_PROBE_TIMEOUT_MS);
|
|
22344
|
-
socket.on("connect", () => answer(true, "sshd is listening on port 22"));
|
|
22345
|
-
socket.on("timeout", () => answer(false, "nothing answered on port 22"));
|
|
22346
|
-
socket.on("error", () => answer(false, "sshd is not running, so nobody can ssh in"));
|
|
22347
|
-
});
|
|
22348
|
-
}
|
|
22349
|
-
async function firstLine(command, args) {
|
|
22350
|
-
if (command.includes("/")) {
|
|
22351
|
-
const reachable = await access(command).then(() => true, () => false);
|
|
22352
|
-
if (!reachable)
|
|
22353
|
-
return { ran: false, why: "absent" };
|
|
22354
|
-
}
|
|
22355
|
-
const answer = await run(command, args, { timeout: PROBE_TIMEOUT_MS }).catch((thrown) => thrown);
|
|
22356
|
-
if (answer instanceof Error)
|
|
22357
|
-
return { ran: false, why: answer.code === "ENOENT" ? "absent" : "broken" };
|
|
22358
|
-
const line = answer.stdout.split("\n")[0]?.trim() ?? "";
|
|
22359
|
-
return line === "" ? { ran: false, why: "broken" } : { ran: true, line: line.slice(0, 200) };
|
|
22360
|
-
}
|
|
22361
|
-
function short(target) {
|
|
22362
|
-
return target.startsWith(os2.homedir()) ? `~${target.slice(os2.homedir().length)}` : target;
|
|
22363
|
-
}
|
|
22364
|
-
var MAC_CHROME = ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"];
|
|
22365
|
-
var LINUX_CHROME = ["google-chrome", "google-chrome-stable", "chromium"];
|
|
22366
|
-
var PROBE_TIMEOUT_MS = 5e3;
|
|
22367
|
-
var SSH_PROBE_TIMEOUT_MS = 1500;
|
|
22368
22443
|
|
|
22369
22444
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
22370
22445
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -22650,10 +22725,10 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
22650
22725
|
return 3;
|
|
22651
22726
|
}
|
|
22652
22727
|
if ("TERM_PROGRAM" in env) {
|
|
22653
|
-
const
|
|
22728
|
+
const version2 = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
22654
22729
|
switch (env.TERM_PROGRAM) {
|
|
22655
22730
|
case "iTerm.app": {
|
|
22656
|
-
return
|
|
22731
|
+
return version2 >= 3 ? 3 : 2;
|
|
22657
22732
|
}
|
|
22658
22733
|
case "Apple_Terminal": {
|
|
22659
22734
|
return 2;
|
|
@@ -22929,7 +23004,6 @@ var LABEL_WIDTH = 13;
|
|
|
22929
23004
|
var BAR_CELLS = 10;
|
|
22930
23005
|
|
|
22931
23006
|
// dist/setup.js
|
|
22932
|
-
var run2 = promisify2(execFile2);
|
|
22933
23007
|
var setup = {
|
|
22934
23008
|
widenPath() {
|
|
22935
23009
|
const current = (process.env.PATH ?? "").split(path3.delimiter).filter((entry) => entry !== "");
|
|
@@ -22937,44 +23011,89 @@ var setup = {
|
|
|
22937
23011
|
if (missing.length > 0)
|
|
22938
23012
|
process.env.PATH = [...current, ...missing].join(path3.delimiter);
|
|
22939
23013
|
},
|
|
22940
|
-
|
|
22941
|
-
|
|
22942
|
-
|
|
22943
|
-
|
|
22944
|
-
|
|
22945
|
-
|
|
22946
|
-
|
|
22947
|
-
|
|
22948
|
-
|
|
22949
|
-
|
|
22950
|
-
const
|
|
22951
|
-
|
|
22952
|
-
|
|
22953
|
-
say?.(ui.
|
|
22954
|
-
|
|
22955
|
-
|
|
22956
|
-
|
|
22957
|
-
|
|
22958
|
-
|
|
22959
|
-
|
|
22960
|
-
|
|
22961
|
-
|
|
22962
|
-
|
|
23014
|
+
workDir() {
|
|
23015
|
+
return path3.join(os4.homedir(), WORK_DIR_NAME);
|
|
23016
|
+
},
|
|
23017
|
+
async cloneRepos({ repos, say }) {
|
|
23018
|
+
if (repos.length === 0)
|
|
23019
|
+
return [];
|
|
23020
|
+
await mkdir(setup.workDir(), { recursive: true });
|
|
23021
|
+
const cloned = [];
|
|
23022
|
+
for (const [index, repo] of repos.entries()) {
|
|
23023
|
+
say?.(ui.progress({ name: repo.name, done: index, total: repos.length }));
|
|
23024
|
+
const at = path3.join(setup.workDir(), repo.name.split("/").pop() ?? repo.name);
|
|
23025
|
+
const outcome = await checkout(repo, at);
|
|
23026
|
+
cloned.push({ name: repo.name, ref: repo.ref, path: at, ...outcome });
|
|
23027
|
+
say?.(`${ui.clear()}${outcome.ok ? ui.ok(`${repo.name} \xB7 ${outcome.detail}`) : ui.bad(repo.name, outcome.detail)}`);
|
|
23028
|
+
}
|
|
23029
|
+
say?.(ui.tally({ done: cloned.filter((repo) => repo.ok).length, total: cloned.length, noun: "cloned" }));
|
|
23030
|
+
return cloned;
|
|
23031
|
+
},
|
|
23032
|
+
async runSteps({ steps, say }) {
|
|
23033
|
+
const results = [];
|
|
23034
|
+
for (const [index, step] of steps.entries()) {
|
|
23035
|
+
say?.(ui.progress({ name: step.name, done: index, total: steps.length }));
|
|
23036
|
+
const startedAt = Date.now();
|
|
23037
|
+
const outcome = await runScript(step.script);
|
|
23038
|
+
results.push({ ...outcome, id: step.id, name: step.name, ms: Date.now() - startedAt });
|
|
23039
|
+
say?.(`${ui.clear()}${outcome.ok ? ui.ok(step.name) : ui.bad(step.name, outcome.detail)}`);
|
|
23040
|
+
}
|
|
23041
|
+
if (results.length > 0) {
|
|
23042
|
+
say?.(ui.tally({ done: results.filter((result) => result.ok).length, total: results.length, noun: "ready" }));
|
|
22963
23043
|
}
|
|
22964
|
-
|
|
22965
|
-
return withReasons(await probe.tools());
|
|
23044
|
+
return results;
|
|
22966
23045
|
}
|
|
22967
23046
|
};
|
|
22968
|
-
function
|
|
22969
|
-
const
|
|
22970
|
-
|
|
22971
|
-
}
|
|
22972
|
-
|
|
22973
|
-
|
|
22974
|
-
|
|
22975
|
-
return
|
|
23047
|
+
async function checkout(repo, at) {
|
|
23048
|
+
const opened = await git(["-C", at, "rev-parse", "--abbrev-ref", "HEAD"]);
|
|
23049
|
+
if (!opened.ok) {
|
|
23050
|
+
const url2 = `https://github.com/${repo.name}.git`;
|
|
23051
|
+
const made = await git(["clone", "--depth", String(CLONE_DEPTH), "--branch", repo.ref, url2, at]);
|
|
23052
|
+
if (!made.ok)
|
|
23053
|
+
return { ok: false, detail: made.detail };
|
|
23054
|
+
return { ok: true, detail: await state({ repo, at, branch: repo.ref, dirty: false }) };
|
|
23055
|
+
}
|
|
23056
|
+
const branch = opened.detail;
|
|
23057
|
+
const dirty = (await git(["-C", at, "status", "--porcelain"])).detail !== "";
|
|
23058
|
+
const pulled = branch === repo.ref && !dirty ? await git(["-C", at, "pull", "--ff-only"]) : null;
|
|
23059
|
+
return { ok: true, detail: await state({ repo, at, branch, dirty, pulled }) };
|
|
23060
|
+
}
|
|
23061
|
+
async function state({ repo, at, branch, dirty, pulled }) {
|
|
23062
|
+
const head = await git(["-C", at, "rev-parse", "--short", "HEAD"]);
|
|
23063
|
+
return [
|
|
23064
|
+
`${branch} @ ${head.detail}`,
|
|
23065
|
+
branch === repo.ref ? "" : `your team asks for ${repo.ref}`,
|
|
23066
|
+
dirty ? "uncommitted work here, so it was left alone" : "",
|
|
23067
|
+
pulled?.ok === false ? `could not pull: ${pulled.detail}` : ""
|
|
23068
|
+
].filter((part) => part !== "").join(" \xB7 ");
|
|
23069
|
+
}
|
|
23070
|
+
function git(argv) {
|
|
23071
|
+
return new Promise((resolve) => {
|
|
23072
|
+
execFile("git", argv, {
|
|
23073
|
+
timeout: CLONE_TIMEOUT_MS,
|
|
23074
|
+
maxBuffer: SCRIPT_BUFFER_BYTES,
|
|
23075
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0", GIT_ASKPASS: "", GIT_LFS_SKIP_SMUDGE: "1" }
|
|
23076
|
+
}, (error51, stdout, stderr) => {
|
|
23077
|
+
if (error51 === null)
|
|
23078
|
+
return resolve({ ok: true, detail: stdout.trim() });
|
|
23079
|
+
resolve({ ok: false, detail: lastLines(`${stderr}
|
|
23080
|
+
${stdout}`) || error51.message.split("\n")[0] || "git failed" });
|
|
23081
|
+
});
|
|
23082
|
+
});
|
|
23083
|
+
}
|
|
23084
|
+
function runScript(script) {
|
|
23085
|
+
return new Promise((resolve) => {
|
|
23086
|
+
execFile("/bin/sh", ["-e", "-c", script], { timeout: STEP_TIMEOUT_MS, maxBuffer: SCRIPT_BUFFER_BYTES }, (error51, stdout, stderr) => {
|
|
23087
|
+
if (error51 === null)
|
|
23088
|
+
return resolve({ ok: true, detail: lastLines(stdout) });
|
|
23089
|
+
resolve({ ok: false, detail: lastLines(`${stderr}
|
|
23090
|
+
${stdout}`) || error51.message.split("\n")[0] || "it failed" });
|
|
23091
|
+
});
|
|
22976
23092
|
});
|
|
22977
23093
|
}
|
|
23094
|
+
function lastLines(output) {
|
|
23095
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => line !== "").slice(-KEPT_LINES).join(" \xB7 ").slice(0, WORKSTATION_STEP_DETAIL_MAX_CHARS);
|
|
23096
|
+
}
|
|
22978
23097
|
function toolDirs() {
|
|
22979
23098
|
const prefix = process.env.npm_config_prefix;
|
|
22980
23099
|
return [
|
|
@@ -22986,56 +23105,17 @@ function toolDirs() {
|
|
|
22986
23105
|
"/usr/local/bin"
|
|
22987
23106
|
];
|
|
22988
23107
|
}
|
|
22989
|
-
var
|
|
22990
|
-
|
|
22991
|
-
|
|
22992
|
-
|
|
22993
|
-
|
|
22994
|
-
|
|
22995
|
-
if (await firstAvailable(["gh"]) !== null)
|
|
22996
|
-
return;
|
|
22997
|
-
await installPackage({ brew: ["gh"], apt: ["gh"], dnf: ["gh"] });
|
|
22998
|
-
}
|
|
22999
|
-
},
|
|
23000
|
-
chrome: {
|
|
23001
|
-
name: "Google Chrome",
|
|
23002
|
-
fix: () => installPackage({ brew: ["--cask", "google-chrome"], apt: ["chromium"], dnf: ["chromium"] })
|
|
23003
|
-
}
|
|
23004
|
-
};
|
|
23005
|
-
async function npmGlobal(name) {
|
|
23006
|
-
await run2("npm", ["install", "-g", name], { timeout: INSTALL_TIMEOUT_MS });
|
|
23007
|
-
}
|
|
23008
|
-
async function installPackage({ brew, apt, dnf }) {
|
|
23009
|
-
if (process.platform === "darwin") {
|
|
23010
|
-
await run2("brew", ["install", ...brew], { timeout: INSTALL_TIMEOUT_MS });
|
|
23011
|
-
return;
|
|
23012
|
-
}
|
|
23013
|
-
const manager = await firstAvailable(["apt-get", "dnf"]);
|
|
23014
|
-
if (manager === null)
|
|
23015
|
-
throw new Error("no package manager this CLI knows how to drive");
|
|
23016
|
-
const packages = manager === "apt-get" ? apt : dnf;
|
|
23017
|
-
await run2("sudo", ["-n", manager, "install", "-y", ...packages], { timeout: INSTALL_TIMEOUT_MS });
|
|
23018
|
-
}
|
|
23019
|
-
async function firstAvailable(commands) {
|
|
23020
|
-
for (const command of commands) {
|
|
23021
|
-
const there = await run2("/bin/sh", ["-c", `command -v ${command}`]).then(() => true, () => false);
|
|
23022
|
-
if (there)
|
|
23023
|
-
return command;
|
|
23024
|
-
}
|
|
23025
|
-
return null;
|
|
23026
|
-
}
|
|
23027
|
-
function firstLine2(message) {
|
|
23028
|
-
return message.split("\n")[0] ?? "it failed";
|
|
23029
|
-
}
|
|
23030
|
-
var tried = /* @__PURE__ */ new Map();
|
|
23031
|
-
var reasons = /* @__PURE__ */ new Map();
|
|
23032
|
-
var INSTALL_TIMEOUT_MS = 18e4;
|
|
23033
|
-
var RETRY_AFTER_MS = 216e5;
|
|
23108
|
+
var WORK_DIR_NAME = "craftspace";
|
|
23109
|
+
var CLONE_DEPTH = 20;
|
|
23110
|
+
var CLONE_TIMEOUT_MS = 9e5;
|
|
23111
|
+
var STEP_TIMEOUT_MS = 6e5;
|
|
23112
|
+
var SCRIPT_BUFFER_BYTES = 4 * 1024 * 1024;
|
|
23113
|
+
var KEPT_LINES = 3;
|
|
23034
23114
|
|
|
23035
23115
|
// dist/update.js
|
|
23036
|
-
import { execFile as
|
|
23037
|
-
import { promisify
|
|
23038
|
-
var
|
|
23116
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
23117
|
+
import { promisify } from "node:util";
|
|
23118
|
+
var run = promisify(execFile2);
|
|
23039
23119
|
var update = {
|
|
23040
23120
|
async latest() {
|
|
23041
23121
|
const answer = await fetch(`${REGISTRY}/${CLI_PACKAGE}/latest`, {
|
|
@@ -23045,17 +23125,17 @@ var update = {
|
|
|
23045
23125
|
if (answer === null || !answer.ok)
|
|
23046
23126
|
return null;
|
|
23047
23127
|
const body = await answer.json().catch(() => null);
|
|
23048
|
-
const
|
|
23049
|
-
return typeof
|
|
23128
|
+
const version2 = isRecord(body) ? body.version : void 0;
|
|
23129
|
+
return typeof version2 === "string" && isNewer(version2) ? version2 : null;
|
|
23050
23130
|
},
|
|
23051
23131
|
async toLatest() {
|
|
23052
|
-
const
|
|
23053
|
-
if (
|
|
23132
|
+
const version2 = await update.latest();
|
|
23133
|
+
if (version2 === null)
|
|
23054
23134
|
return null;
|
|
23055
|
-
const installed = await
|
|
23056
|
-
timeout:
|
|
23135
|
+
const installed = await run("npm", ["install", "--global", "--no-fund", `${CLI_PACKAGE}@${version2}`], {
|
|
23136
|
+
timeout: INSTALL_TIMEOUT_MS
|
|
23057
23137
|
}).then(() => true, () => false);
|
|
23058
|
-
return installed ?
|
|
23138
|
+
return installed ? version2 : null;
|
|
23059
23139
|
}
|
|
23060
23140
|
};
|
|
23061
23141
|
function isNewer(candidate, current = CLI_VERSION) {
|
|
@@ -23069,18 +23149,18 @@ function isNewer(candidate, current = CLI_VERSION) {
|
|
|
23069
23149
|
}
|
|
23070
23150
|
return false;
|
|
23071
23151
|
}
|
|
23072
|
-
function parts(
|
|
23073
|
-
return (/^\d+\.\d+\.\d+/.exec(
|
|
23152
|
+
function parts(version2) {
|
|
23153
|
+
return (/^\d+\.\d+\.\d+/.exec(version2.trim())?.[0] ?? "").split(".").map(Number);
|
|
23074
23154
|
}
|
|
23075
23155
|
function isRecord(value) {
|
|
23076
23156
|
return typeof value === "object" && value !== null;
|
|
23077
23157
|
}
|
|
23078
23158
|
var REGISTRY = "https://registry.npmjs.org";
|
|
23079
23159
|
var REQUEST_TIMEOUT_MS = 1e4;
|
|
23080
|
-
var
|
|
23160
|
+
var INSTALL_TIMEOUT_MS = 18e4;
|
|
23081
23161
|
|
|
23082
23162
|
// dist/machine.js
|
|
23083
|
-
var
|
|
23163
|
+
var run2 = promisify2(execFile3);
|
|
23084
23164
|
var machine = {
|
|
23085
23165
|
home() {
|
|
23086
23166
|
return process.env.CRAFTSPACE_CLI_HOME ?? path4.join(os5.homedir(), ".craftspace");
|
|
@@ -23102,15 +23182,13 @@ var machine = {
|
|
|
23102
23182
|
},
|
|
23103
23183
|
schema: MachineLoginResponseSchema
|
|
23104
23184
|
});
|
|
23105
|
-
await
|
|
23185
|
+
await mkdir2(machine.home(), { recursive: true, mode: 448 });
|
|
23106
23186
|
await writeFile(configPath(), JSON.stringify({ url: url2, machineId: answer.machine.id }, null, 2), { mode: 384 });
|
|
23107
23187
|
await writeFile(tokenPath(), token, { mode: 384 });
|
|
23108
23188
|
await writeAgentConfigs({ url: url2, token, writes: answer.write });
|
|
23109
23189
|
await installService();
|
|
23110
|
-
|
|
23111
|
-
|
|
23112
|
-
tools: await setup.run({ install, rewire, say: ui.say })
|
|
23113
|
-
};
|
|
23190
|
+
if (install)
|
|
23191
|
+
await machine.beatOnce(ui.say);
|
|
23114
23192
|
return answer.machine;
|
|
23115
23193
|
},
|
|
23116
23194
|
async controlPlane(override) {
|
|
@@ -23147,8 +23225,9 @@ ${ui.ok(`Signed in as ${signed.ownerName}. This machine is ${ui.name(signed.name
|
|
|
23147
23225
|
const found = await withAuth(await signedInOrAsk(), (auth) => call({ ...auth, method: "GET", path: "/api/machines/me", schema: MachineSchema }));
|
|
23148
23226
|
return { machine: found.value, url: found.auth.url };
|
|
23149
23227
|
},
|
|
23150
|
-
async beatOnce() {
|
|
23228
|
+
async beatOnce(say) {
|
|
23151
23229
|
const { url: url2, token } = await requireSignedIn();
|
|
23230
|
+
const built = await readEnvironment();
|
|
23152
23231
|
const answer = await call({
|
|
23153
23232
|
url: url2,
|
|
23154
23233
|
token,
|
|
@@ -23159,17 +23238,26 @@ ${ui.ok(`Signed in as ${signed.ownerName}. This machine is ${ui.name(signed.name
|
|
|
23159
23238
|
...load2(),
|
|
23160
23239
|
sessions: await readSessions(),
|
|
23161
23240
|
runs: drainReports(),
|
|
23162
|
-
tools: await
|
|
23241
|
+
tools: await checks(),
|
|
23242
|
+
environment: built?.results ?? [],
|
|
23243
|
+
templateId: built?.templateId ?? null,
|
|
23244
|
+
workDir: setup.workDir(),
|
|
23245
|
+
repos: built?.repos ?? [],
|
|
23163
23246
|
sshUser: os5.userInfo().username
|
|
23164
23247
|
},
|
|
23165
23248
|
schema: MachineBeatResponseSchema
|
|
23166
23249
|
});
|
|
23167
23250
|
await writeAuthorizedKeys(answer.authorizedKeys);
|
|
23251
|
+
const building2 = buildEnvironment(answer.environment, say);
|
|
23252
|
+
if (say === void 0)
|
|
23253
|
+
void building2.catch(() => void 0);
|
|
23254
|
+
else
|
|
23255
|
+
await building2;
|
|
23168
23256
|
for (const work of answer.work) {
|
|
23169
23257
|
if (running.has(work.id))
|
|
23170
23258
|
continue;
|
|
23171
23259
|
running.add(work.id);
|
|
23172
|
-
void runner.unattended({ work, onProgress: report }).then(report).catch((error51) => report({ id: work.id, state: "failed", output: messageOf(error51) })).finally(() => running.delete(work.id));
|
|
23260
|
+
void runner.unattended({ work, cwd: startIn(built), onProgress: report }).then(report).catch((error51) => report({ id: work.id, state: "failed", output: messageOf(error51) })).finally(() => running.delete(work.id));
|
|
23173
23261
|
}
|
|
23174
23262
|
return running.size > 0 || answer.work.length > 0;
|
|
23175
23263
|
},
|
|
@@ -23178,7 +23266,7 @@ ${ui.ok(`Signed in as ${signed.ownerName}. This machine is ${ui.name(signed.name
|
|
|
23178
23266
|
let busy = false;
|
|
23179
23267
|
let checkedAt = 0;
|
|
23180
23268
|
for (; ; ) {
|
|
23181
|
-
if (!busy && Date.now() - checkedAt > UPDATE_EVERY_MS) {
|
|
23269
|
+
if (!busy && (failures > 2 || Date.now() - checkedAt > UPDATE_EVERY_MS)) {
|
|
23182
23270
|
checkedAt = Date.now();
|
|
23183
23271
|
const moved = await update.toLatest();
|
|
23184
23272
|
if (moved !== null) {
|
|
@@ -23240,7 +23328,7 @@ async function pick2(machines) {
|
|
|
23240
23328
|
choices: machines.map((candidate) => ({
|
|
23241
23329
|
name: `${candidate.name.padEnd(24)} ${candidate.state.padEnd(12)} ${specs(candidate)} ${beat(candidate)}`,
|
|
23242
23330
|
value: candidate,
|
|
23243
|
-
|
|
23331
|
+
disabled: candidate.sshAddress === null ? "(no address yet, so nothing to open)" : false
|
|
23244
23332
|
})),
|
|
23245
23333
|
pageSize: 12
|
|
23246
23334
|
});
|
|
@@ -23292,13 +23380,74 @@ ${ui.attention("No workstations here yet.")}
|
|
|
23292
23380
|
ui.say("\n");
|
|
23293
23381
|
return 1;
|
|
23294
23382
|
}
|
|
23295
|
-
async function
|
|
23383
|
+
async function checks() {
|
|
23296
23384
|
if (probed !== null && Date.now() - probed.at < PROBE_EVERY_MS)
|
|
23297
23385
|
return probed.tools;
|
|
23298
|
-
const
|
|
23386
|
+
const first = await probe.tools();
|
|
23387
|
+
const unwired = first.some((tool) => tool.id === "brain" && !tool.ok);
|
|
23388
|
+
const found = unwired && installs() ? await rewire().then(() => probe.tools(), () => first) : first;
|
|
23299
23389
|
probed = { at: Date.now(), tools: found };
|
|
23300
23390
|
return found;
|
|
23301
23391
|
}
|
|
23392
|
+
async function buildEnvironment(next, say) {
|
|
23393
|
+
if (building || !installs() || next.templateId === null)
|
|
23394
|
+
return;
|
|
23395
|
+
const built = await readEnvironment();
|
|
23396
|
+
const buildsSteps = buildIsDue(built, next.templateId);
|
|
23397
|
+
const clonesRepos = cloneIsDue(built, next.repos);
|
|
23398
|
+
if (!buildsSteps && !clonesRepos)
|
|
23399
|
+
return;
|
|
23400
|
+
building = true;
|
|
23401
|
+
try {
|
|
23402
|
+
let results = built?.results ?? [];
|
|
23403
|
+
let repos = built?.repos ?? [];
|
|
23404
|
+
if (buildsSteps) {
|
|
23405
|
+
say?.(ui.heading(`Building the ${next.steps.length} setup scripts your team runs on every box`));
|
|
23406
|
+
results = await setup.runSteps({ steps: next.steps, say });
|
|
23407
|
+
}
|
|
23408
|
+
if (clonesRepos) {
|
|
23409
|
+
say?.(ui.heading(`Cloning the ${next.repos.length} repos your team works in, into ${setup.workDir()}`));
|
|
23410
|
+
repos = await setup.cloneRepos({ repos: next.repos, say });
|
|
23411
|
+
await acceptClaudeGates(["craftspace"], repos.filter((repo) => repo.ok).map((repo) => repo.path));
|
|
23412
|
+
}
|
|
23413
|
+
await writeEnvironment({ templateId: next.templateId, results, repos, at: Date.now() });
|
|
23414
|
+
} finally {
|
|
23415
|
+
building = false;
|
|
23416
|
+
}
|
|
23417
|
+
}
|
|
23418
|
+
function cloneIsDue(built, wanted) {
|
|
23419
|
+
const cloned = built?.repos ?? [];
|
|
23420
|
+
if (wanted.length === 0 && cloned.length === 0)
|
|
23421
|
+
return false;
|
|
23422
|
+
if (wanted.length !== cloned.length)
|
|
23423
|
+
return true;
|
|
23424
|
+
const missing = wanted.some((repo) => !cloned.some((seen) => seen.name === repo.name && seen.ref === repo.ref && seen.ok));
|
|
23425
|
+
return missing || Date.now() - (built?.at ?? 0) > REBUILD_AFTER_MS;
|
|
23426
|
+
}
|
|
23427
|
+
function startIn(built) {
|
|
23428
|
+
return built?.repos.find((repo) => repo.ok)?.path ?? os5.homedir();
|
|
23429
|
+
}
|
|
23430
|
+
function buildIsDue(built, templateId) {
|
|
23431
|
+
if (built === null || built.templateId !== templateId)
|
|
23432
|
+
return true;
|
|
23433
|
+
if (built.results.every((result) => result.ok))
|
|
23434
|
+
return false;
|
|
23435
|
+
return Date.now() - built.at > REBUILD_AFTER_MS;
|
|
23436
|
+
}
|
|
23437
|
+
async function readEnvironment() {
|
|
23438
|
+
const raw = await readFile2(environmentPath(), "utf8").catch(() => null);
|
|
23439
|
+
if (raw === null)
|
|
23440
|
+
return null;
|
|
23441
|
+
const parsed = BuiltSchema.safeParse(JSON.parse(raw));
|
|
23442
|
+
return parsed.success ? parsed.data : null;
|
|
23443
|
+
}
|
|
23444
|
+
async function writeEnvironment(built) {
|
|
23445
|
+
await mkdir2(machine.home(), { recursive: true, mode: 448 });
|
|
23446
|
+
await writeFile(environmentPath(), JSON.stringify(built, null, 2), { mode: 384 });
|
|
23447
|
+
}
|
|
23448
|
+
function installs() {
|
|
23449
|
+
return process.env.CRAFTSPACE_NO_INSTALL !== "1";
|
|
23450
|
+
}
|
|
23302
23451
|
async function rewire() {
|
|
23303
23452
|
const { url: url2, token } = await requireSignedIn();
|
|
23304
23453
|
await writeAgentConfigs({ url: url2, token, writes: [] });
|
|
@@ -23359,7 +23508,7 @@ ${ui.note("Picking up where you left off.")}
|
|
|
23359
23508
|
}
|
|
23360
23509
|
async function openInBrowser(url2) {
|
|
23361
23510
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
23362
|
-
await
|
|
23511
|
+
await run2(opener, [url2]).catch(() => void 0);
|
|
23363
23512
|
}
|
|
23364
23513
|
function tokenIn(line) {
|
|
23365
23514
|
return /cst_[A-Za-z0-9_-]+/.exec(line)?.[0];
|
|
@@ -23370,8 +23519,8 @@ async function ensureKey() {
|
|
|
23370
23519
|
const existing = await readFile2(pub, "utf8").catch(() => null);
|
|
23371
23520
|
if (existing !== null)
|
|
23372
23521
|
return existing.trim();
|
|
23373
|
-
await
|
|
23374
|
-
await
|
|
23522
|
+
await mkdir2(machine.home(), { recursive: true, mode: 448 });
|
|
23523
|
+
await run2("ssh-keygen", ["-t", "ed25519", "-N", "", "-q", "-f", priv, "-C", `craftspace-${os5.hostname()}`]);
|
|
23375
23524
|
return (await readFile2(pub, "utf8")).trim();
|
|
23376
23525
|
}
|
|
23377
23526
|
async function readConfig() {
|
|
@@ -23410,7 +23559,7 @@ ${KEYS_END}
|
|
|
23410
23559
|
const next = `${trimEnd(before)}${trimEnd(before) === "" ? "" : "\n"}${block}${after.replace(/^\n/, "")}`;
|
|
23411
23560
|
if (next === current)
|
|
23412
23561
|
return;
|
|
23413
|
-
await
|
|
23562
|
+
await mkdir2(path4.dirname(target), { recursive: true, mode: 448 });
|
|
23414
23563
|
await writeFile(target, next, { mode: 384 });
|
|
23415
23564
|
}
|
|
23416
23565
|
function trimEnd(text) {
|
|
@@ -23421,7 +23570,7 @@ async function writeAgentConfigs({ url: url2, token, writes }) {
|
|
|
23421
23570
|
const owned = [];
|
|
23422
23571
|
for (const write of planned) {
|
|
23423
23572
|
const target = expand(write.path);
|
|
23424
|
-
await
|
|
23573
|
+
await mkdir2(path4.dirname(target), { recursive: true });
|
|
23425
23574
|
const current = await readFile2(target, "utf8").catch(() => null);
|
|
23426
23575
|
if (current !== null)
|
|
23427
23576
|
await writeFile(`${target}.craftspace-backup`, current, { flag: "wx" }).catch(() => void 0);
|
|
@@ -23436,22 +23585,29 @@ async function writeAgentConfigs({ url: url2, token, writes }) {
|
|
|
23436
23585
|
function serversIn(writes) {
|
|
23437
23586
|
return writes.flatMap((write) => isPlainObject3(write.contents.mcpServers) ? Object.keys(write.contents.mcpServers) : []);
|
|
23438
23587
|
}
|
|
23439
|
-
async function acceptClaudeGates(servers) {
|
|
23588
|
+
async function acceptClaudeGates(servers, dirs = [os5.homedir()]) {
|
|
23440
23589
|
const target = path4.join(os5.homedir(), ".claude.json");
|
|
23441
23590
|
const raw = await readFile2(target, "utf8").catch(() => null);
|
|
23442
23591
|
if (raw === null)
|
|
23443
23592
|
return;
|
|
23444
23593
|
const parsed = JSON.parse(raw);
|
|
23445
23594
|
const projects = isPlainObject3(parsed.projects) ? parsed.projects : {};
|
|
23446
|
-
const
|
|
23447
|
-
|
|
23448
|
-
const
|
|
23449
|
-
|
|
23595
|
+
const opened = { ...projects };
|
|
23596
|
+
let moved = false;
|
|
23597
|
+
for (const dir of dirs) {
|
|
23598
|
+
const found = opened[dir];
|
|
23599
|
+
const here2 = isPlainObject3(found) ? { ...found } : {};
|
|
23600
|
+
const enabled = /* @__PURE__ */ new Set([...asArray(here2.enabledMcpjsonServers), ...servers]);
|
|
23601
|
+
if (here2.hasTrustDialogAccepted === true && enabled.size === asArray(here2.enabledMcpjsonServers).length)
|
|
23602
|
+
continue;
|
|
23603
|
+
here2.hasTrustDialogAccepted = true;
|
|
23604
|
+
here2.enabledMcpjsonServers = [...enabled];
|
|
23605
|
+
opened[dir] = here2;
|
|
23606
|
+
moved = true;
|
|
23607
|
+
}
|
|
23608
|
+
if (!moved)
|
|
23450
23609
|
return;
|
|
23451
|
-
|
|
23452
|
-
here2.enabledMcpjsonServers = [...enabled];
|
|
23453
|
-
const next = { ...parsed, projects: { ...projects, [os5.homedir()]: here2 } };
|
|
23454
|
-
await writeFile(target, `${JSON.stringify(next, null, 2)}
|
|
23610
|
+
await writeFile(target, `${JSON.stringify({ ...parsed, projects: opened }, null, 2)}
|
|
23455
23611
|
`, { mode: 384 });
|
|
23456
23612
|
}
|
|
23457
23613
|
function asArray(value) {
|
|
@@ -23502,30 +23658,31 @@ async function installService() {
|
|
|
23502
23658
|
return;
|
|
23503
23659
|
if (process.platform === "linux") {
|
|
23504
23660
|
const dir = path4.join(os5.homedir(), ".config", "systemd", "user");
|
|
23505
|
-
await
|
|
23661
|
+
await mkdir2(dir, { recursive: true });
|
|
23506
23662
|
await writeFile(path4.join(dir, `${SERVICE_NAME}.service`), systemdUnit());
|
|
23507
|
-
await
|
|
23508
|
-
await
|
|
23509
|
-
await
|
|
23663
|
+
await run2("loginctl", ["enable-linger", os5.userInfo().username]).catch(() => void 0);
|
|
23664
|
+
await run2("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
|
|
23665
|
+
await run2("systemctl", ["--user", "enable", SERVICE_NAME]).catch(() => void 0);
|
|
23666
|
+
await run2("systemctl", ["--user", "restart", SERVICE_NAME]).catch(() => void 0);
|
|
23510
23667
|
return;
|
|
23511
23668
|
}
|
|
23512
23669
|
if (process.platform === "darwin") {
|
|
23513
23670
|
const target = path4.join(os5.homedir(), "Library", "LaunchAgents", `${LAUNCH_LABEL}.plist`);
|
|
23514
|
-
await
|
|
23671
|
+
await mkdir2(path4.dirname(target), { recursive: true });
|
|
23515
23672
|
await writeFile(target, launchdPlist());
|
|
23516
|
-
await
|
|
23517
|
-
await
|
|
23673
|
+
await run2("launchctl", ["unload", target]).catch(() => void 0);
|
|
23674
|
+
await run2("launchctl", ["load", target]).catch(() => void 0);
|
|
23518
23675
|
}
|
|
23519
23676
|
}
|
|
23520
23677
|
async function uninstallService() {
|
|
23521
23678
|
if (process.platform === "linux") {
|
|
23522
|
-
await
|
|
23679
|
+
await run2("systemctl", ["--user", "disable", "--now", SERVICE_NAME]).catch(() => void 0);
|
|
23523
23680
|
await rm(path4.join(os5.homedir(), ".config", "systemd", "user", `${SERVICE_NAME}.service`), { force: true });
|
|
23524
23681
|
return;
|
|
23525
23682
|
}
|
|
23526
23683
|
if (process.platform === "darwin") {
|
|
23527
23684
|
const target = path4.join(os5.homedir(), "Library", "LaunchAgents", `${LAUNCH_LABEL}.plist`);
|
|
23528
|
-
await
|
|
23685
|
+
await run2("launchctl", ["unload", target]).catch(() => void 0);
|
|
23529
23686
|
await rm(target, { force: true });
|
|
23530
23687
|
}
|
|
23531
23688
|
}
|
|
@@ -23562,10 +23719,10 @@ function here() {
|
|
|
23562
23719
|
return `${process.execPath} ${entryPath()}`;
|
|
23563
23720
|
}
|
|
23564
23721
|
async function serviceRunning() {
|
|
23565
|
-
return await
|
|
23722
|
+
return await run2("systemctl", ["--user", "is-active", SERVICE_NAME]).catch(() => null) !== null;
|
|
23566
23723
|
}
|
|
23567
23724
|
async function userLingers() {
|
|
23568
|
-
const shown = await
|
|
23725
|
+
const shown = await run2("loginctl", ["show-user", os5.userInfo().username, "-p", "Linger"]).catch(() => null);
|
|
23569
23726
|
return shown?.stdout.includes("Linger=yes") === true;
|
|
23570
23727
|
}
|
|
23571
23728
|
function entryPath() {
|
|
@@ -23583,6 +23740,9 @@ function tokenPath() {
|
|
|
23583
23740
|
function ownedPath() {
|
|
23584
23741
|
return path4.join(machine.home(), "owned.json");
|
|
23585
23742
|
}
|
|
23743
|
+
function environmentPath() {
|
|
23744
|
+
return path4.join(machine.home(), "environment.json");
|
|
23745
|
+
}
|
|
23586
23746
|
function load2() {
|
|
23587
23747
|
const cores = Math.max(1, os5.cpus().length);
|
|
23588
23748
|
const busy = Math.min(100, (os5.loadavg()[0] ?? 0) / cores * 100);
|
|
@@ -23601,6 +23761,12 @@ function messageOf(error51) {
|
|
|
23601
23761
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
23602
23762
|
}
|
|
23603
23763
|
var ConfigSchema = external_exports.object({ url: external_exports.string(), machineId: external_exports.string() });
|
|
23764
|
+
var BuiltSchema = external_exports.object({
|
|
23765
|
+
templateId: external_exports.string(),
|
|
23766
|
+
results: external_exports.array(WorkstationStepResultSchema),
|
|
23767
|
+
repos: external_exports.array(MachineRepoSchema).default([]),
|
|
23768
|
+
at: external_exports.number()
|
|
23769
|
+
});
|
|
23604
23770
|
var OwnedSchema = external_exports.object({ paths: external_exports.array(external_exports.string()) });
|
|
23605
23771
|
var SERVICE_NAME = "craftspace";
|
|
23606
23772
|
var LAUNCH_LABEL = "app.craftspace.machine";
|
|
@@ -23629,7 +23795,9 @@ var PORTABLE_TERMS = /* @__PURE__ */ new Set([
|
|
|
23629
23795
|
var LINGER_LINE = `sudo loginctl enable-linger ${os5.userInfo().username}`;
|
|
23630
23796
|
var DEFAULT_URL = process.env.CRAFTSPACE_URL ?? "https://craftspace.app";
|
|
23631
23797
|
var PROBE_EVERY_MS = 3e5;
|
|
23798
|
+
var REBUILD_AFTER_MS = 216e5;
|
|
23632
23799
|
var probed = null;
|
|
23800
|
+
var building = false;
|
|
23633
23801
|
var reports = /* @__PURE__ */ new Map();
|
|
23634
23802
|
var running = /* @__PURE__ */ new Set();
|
|
23635
23803
|
|