@telepath-computer/television 0.1.191 → 0.1.193

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/cli.cjs CHANGED
@@ -33250,6 +33250,7 @@ var require_websocket_server = __commonJS({
33250
33250
  // src/index.ts
33251
33251
  var index_exports = {};
33252
33252
  __export(index_exports, {
33253
+ PORT_ZERO_WARNING: () => PORT_ZERO_WARNING,
33253
33254
  inspectTelemetryBuildConfig: () => inspectTelemetryBuildConfig,
33254
33255
  listVisibleCLICommandNames: () => listVisibleCLICommandNames,
33255
33256
  resolveBundledSkillsRoot: () => resolveBundledSkillsRoot,
@@ -34039,7 +34040,10 @@ var ScreenClient = class {
34039
34040
  if (screens.length === 1) {
34040
34041
  return screens[0].id;
34041
34042
  }
34042
- throw this.#http.createError(
34043
+ if (screens.length === 0) {
34044
+ throw new ValidationError("screenID is required, but no screens exist.");
34045
+ }
34046
+ throw new ValidationError(
34043
34047
  `screenID is required when multiple screens exist. Available screens: ${formatScreenChoices(screens)}`
34044
34048
  );
34045
34049
  }
@@ -34219,6 +34223,7 @@ var TELEVISION_STORAGE_PATH_ENV = "TELEVISION_STORAGE_PATH";
34219
34223
  var TELEVISION_PORT_ENV = "TELEVISION_PORT";
34220
34224
  var TELEVISION_ACP_AGENT_ENV = "TELEVISION_ACP_AGENT";
34221
34225
  var TELEVISION_DEVELOPER_HOME_ENV = "TELEVISION_DEVELOPER_HOME";
34226
+ var MAX_PORT = 65535;
34222
34227
  var TELEMETRY_CONTROL_ENV_VARS = [
34223
34228
  "DO_NOT_TRACK",
34224
34229
  "CI",
@@ -34259,11 +34264,17 @@ function getTelevisionStoragePath() {
34259
34264
  }
34260
34265
  function getTelevisionPortEnv() {
34261
34266
  const rawPort = process.env[TELEVISION_PORT_ENV];
34262
- if (!rawPort) {
34267
+ if (rawPort === void 0 || rawPort.trim() === "") {
34263
34268
  return void 0;
34264
34269
  }
34265
- const port = Number.parseInt(rawPort, 10);
34266
- return Number.isInteger(port) ? port : void 0;
34270
+ if (!/^\d+$/.test(rawPort)) {
34271
+ throw new Error(`${TELEVISION_PORT_ENV} must be a decimal integer between 0 and ${MAX_PORT}.`);
34272
+ }
34273
+ const port = Number(rawPort);
34274
+ if (!Number.isSafeInteger(port) || port < 0 || port > MAX_PORT) {
34275
+ throw new Error(`${TELEVISION_PORT_ENV} must be a decimal integer between 0 and ${MAX_PORT}.`);
34276
+ }
34277
+ return port;
34267
34278
  }
34268
34279
  function resolveACPAgentProfile(env = process.env) {
34269
34280
  const rawAgent = env[TELEVISION_ACP_AGENT_ENV];
@@ -52558,7 +52569,7 @@ function disabledTelemetryRuntime() {
52558
52569
 
52559
52570
  // ../server/src/updates/version.ts
52560
52571
  function readVersionStamp() {
52561
- if ("0.1.191".length > 0) return "0.1.191";
52572
+ if ("0.1.193".length > 0) return "0.1.193";
52562
52573
  return void 0;
52563
52574
  }
52564
52575
  function resolveUpdateReleaseVersion(env = process.env, stamp = readVersionStamp()) {
@@ -53058,8 +53069,8 @@ var Server = class {
53058
53069
  };
53059
53070
  };
53060
53071
  function readServerPackageVersion() {
53061
- if ("0.1.191".length > 0) {
53062
- return telemetryVersion("0.1.191");
53072
+ if ("0.1.193".length > 0) {
53073
+ return telemetryVersion("0.1.193");
53063
53074
  }
53064
53075
  const packageJsonPath = import_node_path11.default.resolve(import_node_path11.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
53065
53076
  if (!(0, import_node_fs9.existsSync)(packageJsonPath)) return telemetryVersion("0.0.0");
@@ -54575,10 +54586,12 @@ var import_meta2 = {};
54575
54586
  var DAEMON_NAME = "com.television.server";
54576
54587
  var TELEMETRY_LAUNCH_MODE_ENV = "TELEVISION_LAUNCH_MODE";
54577
54588
  var SKILL_INSTALL_TELEMETRY_TIMEOUT_MS2 = 1e3;
54578
- var MAX_PORT = 65535;
54589
+ var MAX_PORT2 = 65535;
54579
54590
  var MAX_PROCESS_EXIT_STATUS = 255;
54580
54591
  var HTTP_UNAUTHORIZED_STATUS2 = 401;
54581
54592
  var HELP_POINTER = "Television ships bundled skills. The main skill is `television` \u2014 keep its guidance available for screens, lifecycle, the `tv` CLI, and artifact workflow. Re-read it only if it is not already in context or you know the installed skill changed. Additional `tv-*` skills cover specialized artifact types and theming. Install all bundled skills with `tv skills install <path>` (e.g. ~/.openclaw/skills) or `tv skills install -i`.";
54593
+ var PORT_ZERO_WARNING = "WARNING: --port 0 can make Television hard for later agent CLI commands to rediscover. Use a stable port and export TELEVISION_PORT in the user's environment when agents need to find the server later.";
54594
+ var SAFE_ARG_PATTERN = /^[A-Za-z0-9_./:@%+=,-]+$/;
54582
54595
  var CLIDirectiveError = class extends Error {
54583
54596
  name = "CLIDirectiveError";
54584
54597
  };
@@ -54636,8 +54649,8 @@ function resolveVercelSkillsInstallerBin() {
54636
54649
  return localRequire.resolve("skills/bin/cli.mjs");
54637
54650
  }
54638
54651
  function readCLIVersion() {
54639
- if ("0.1.191".length > 0) {
54640
- return "0.1.191";
54652
+ if ("0.1.193".length > 0) {
54653
+ return "0.1.193";
54641
54654
  }
54642
54655
  const devPackageJsonPath = import_node_path17.default.join(getDevPackageDir(), "package.json");
54643
54656
  if (!(0, import_node_fs14.existsSync)(devPackageJsonPath)) {
@@ -54682,9 +54695,14 @@ function buildArtifactWorkflowHelpNote(includeHTMLNote) {
54682
54695
  }
54683
54696
  return lines.join("\n");
54684
54697
  }
54685
- function commandNameFromArgv(argv) {
54686
- const parts = argv.filter((value) => !value.startsWith("-"));
54687
- return parts.length > 0 ? parts.join(" ") : "tv";
54698
+ function formatArgvToken(value) {
54699
+ return SAFE_ARG_PATTERN.test(value) ? value : JSON.stringify(value);
54700
+ }
54701
+ function formatEnteredInvocation(argv) {
54702
+ return ["tv", ...argv.map(formatArgvToken)].join(" ");
54703
+ }
54704
+ function formatEnteredCommand(argv) {
54705
+ return argv.length > 0 ? argv.map(formatArgvToken).join(" ") : "tv";
54688
54706
  }
54689
54707
  function storagePathFromArgv(argv) {
54690
54708
  for (let index = 0; index < argv.length; index += 1) {
@@ -54707,6 +54725,9 @@ function formatCLIError(error48, argv = []) {
54707
54725
  if (error48 instanceof CLIDirectiveError) {
54708
54726
  return error48.message;
54709
54727
  }
54728
+ if (error48 instanceof ValidationError) {
54729
+ return ensureHelpPointer(error48.message);
54730
+ }
54710
54731
  if (typeof error48 === "object" && error48 !== null && "serverURL" in error48 && "message" in error48) {
54711
54732
  const serverURL = String(error48.serverURL);
54712
54733
  const message = String(error48.message);
@@ -54724,9 +54745,12 @@ function formatCLIError(error48, argv = []) {
54724
54745
  return error48 instanceof Error ? error48.message : String(error48);
54725
54746
  }
54726
54747
  function parsePortOption(value) {
54727
- const port = Number.parseInt(value, 10);
54728
- if (!Number.isInteger(port) || port < 0 || port > MAX_PORT) {
54729
- throw new InvalidArgumentError(`port must be an integer between 0 and ${MAX_PORT}`);
54748
+ if (!/^\d+$/.test(value)) {
54749
+ throw new InvalidArgumentError(`port must be a decimal integer between 0 and ${MAX_PORT2}`);
54750
+ }
54751
+ const port = Number(value);
54752
+ if (!Number.isSafeInteger(port) || port < 0 || port > MAX_PORT2) {
54753
+ throw new InvalidArgumentError(`port must be a decimal integer between 0 and ${MAX_PORT2}`);
54730
54754
  }
54731
54755
  return port;
54732
54756
  }
@@ -54734,7 +54758,14 @@ function collectOption(value, previous = []) {
54734
54758
  return [...previous, value];
54735
54759
  }
54736
54760
  function resolveClientPort(port) {
54737
- return port ?? getTelevisionPortEnv() ?? DEFAULT_SERVER_PORT;
54761
+ if (port !== void 0) {
54762
+ return port;
54763
+ }
54764
+ try {
54765
+ return getTelevisionPortEnv() ?? DEFAULT_SERVER_PORT;
54766
+ } catch (error48) {
54767
+ throw createDirectiveError(error48 instanceof Error ? error48.message : String(error48));
54768
+ }
54738
54769
  }
54739
54770
  function buildLocalServerURL(port) {
54740
54771
  return buildServerURL(DEFAULT_SERVER_HOST, resolveClientPort(port));
@@ -54753,12 +54784,13 @@ function resolveServeAuth(argv, hasListen) {
54753
54784
  return void 0;
54754
54785
  }
54755
54786
  function resolveStaticDir() {
54756
- if (!process.argv[1]) {
54757
- return void 0;
54787
+ if (process.argv[1]) {
54788
+ const entryDir = import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1]));
54789
+ const resolved = import_node_path17.default.resolve(entryDir, "./web");
54790
+ return (0, import_node_fs14.existsSync)(import_node_path17.default.join(resolved, "index.html")) ? resolved : void 0;
54758
54791
  }
54759
- const entryDir = import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1]));
54760
- const resolved = import_node_path17.default.resolve(entryDir, "./web");
54761
- return (0, import_node_fs14.existsSync)(import_node_path17.default.join(resolved, "index.html")) ? resolved : void 0;
54792
+ const devStaticPath = import_node_path17.default.resolve(getDevPackageDir(), "../web/dist");
54793
+ return (0, import_node_fs14.existsSync)(import_node_path17.default.join(devStaticPath, "index.html")) ? devStaticPath : void 0;
54762
54794
  }
54763
54795
  function resolveBundledViewsPath() {
54764
54796
  if (process.argv[1]) {
@@ -54867,29 +54899,30 @@ function formatScreenRemovalResult(result) {
54867
54899
  return header;
54868
54900
  }
54869
54901
  function formatCommanderError(argv, error48) {
54870
- const commandName = commandNameFromArgv(argv);
54902
+ const enteredInvocation = formatEnteredInvocation(argv);
54903
+ const enteredCommand = formatEnteredCommand(argv);
54871
54904
  const optionMatch = /option '([^']+)'/.exec(error48.message);
54872
54905
  const argumentMatch = /missing required argument '([^']+)'/.exec(error48.message);
54873
54906
  if (error48.code === "commander.unknownCommand") {
54874
- return createDirectiveError(`Unknown tv command: ${commandName}.`);
54907
+ return createDirectiveError(`Unknown tv command: ${enteredCommand}.`);
54875
54908
  }
54876
- if (commandName === "help" && error48.code === "commander.excessArguments") {
54877
- return createDirectiveError("tv help does not accept additional arguments.");
54909
+ if (argv[0] === "help" && error48.code === "commander.excessArguments") {
54910
+ return createDirectiveError(`${enteredInvocation} does not accept additional arguments.`);
54878
54911
  }
54879
54912
  if (error48.code === "commander.unknownOption") {
54880
54913
  const optionText = optionMatch?.[1] ?? "that option";
54881
- return createDirectiveError(`tv ${commandName} does not support ${optionText}.`);
54914
+ return createDirectiveError(`${enteredInvocation} does not support ${optionText}.`);
54882
54915
  }
54883
54916
  if (error48.code === "commander.missingMandatoryOptionValue") {
54884
54917
  const optionText = optionMatch?.[1] ?? "the required option";
54885
- return createDirectiveError(`tv ${commandName} requires ${optionText}.`);
54918
+ return createDirectiveError(`${enteredInvocation} requires ${optionText}.`);
54886
54919
  }
54887
54920
  if (error48.code === "commander.missingArgument") {
54888
54921
  const argumentText = argumentMatch ? `<${argumentMatch[1]}>` : "the required argument";
54889
- return createDirectiveError(`tv ${commandName} requires ${argumentText}.`);
54922
+ return createDirectiveError(`${enteredInvocation} requires ${argumentText}.`);
54890
54923
  }
54891
54924
  if (error48.code === "commander.invalidArgument") {
54892
- return createDirectiveError(`tv ${commandName} received an invalid argument: ${error48.message.replace(/^error:\s*/, "")}`);
54925
+ return createDirectiveError(`${enteredInvocation} received an invalid argument: ${error48.message.replace(/^error:\s*/, "")}`);
54893
54926
  }
54894
54927
  return null;
54895
54928
  }
@@ -54939,7 +54972,7 @@ function createEnvironment(environment) {
54939
54972
  createServer: environment.createServer ?? ((options) => new Server({
54940
54973
  // `tv serve` always enables the onboarding installer, passing the
54941
54974
  // resolved content root when one resolved
54942
- // (specs/arch/onboarding/content.md CLI path resolution).
54975
+ // (specs/arch/cli/index.md, build and packaged asset layout).
54943
54976
  store: new ServerStore({
54944
54977
  storagePath: options.storagePath ?? getTelevisionStoragePath(),
54945
54978
  ...options.bundledViewsPath ? { bundledViewsPath: options.bundledViewsPath } : {},
@@ -54989,7 +55022,13 @@ function resolveClientStoragePath(storagePath) {
54989
55022
  }
54990
55023
  function createProgram(env, argv = []) {
54991
55024
  const program2 = new Command();
55025
+ const warnForExplicitPortZero = (port) => {
55026
+ if (port === 0) {
55027
+ writeLine(env.stderr, PORT_ZERO_WARNING);
55028
+ }
55029
+ };
54992
55030
  const createAuthenticatedClient = (options = {}) => {
55031
+ warnForExplicitPortZero(options.port);
54993
55032
  return env.createClient(
54994
55033
  buildLocalServerURL(options.port),
54995
55034
  readAuthToken(resolveClientStoragePath(options.storagePath))
@@ -55017,7 +55056,7 @@ function createProgram(env, argv = []) {
55017
55056
  log(storagePath, "persisted service uninstalled", { daemonName: DAEMON_NAME, outcome });
55018
55057
  writeJSON(env.stdout, { status: "stopped" });
55019
55058
  };
55020
- program2.name("tv").description("Television \u2014 virtual display for agents").version(readCLIVersion()).showSuggestionAfterError(false).addHelpText("after", buildAgentHelpNote()).configureOutput({
55059
+ program2.name("tv").description("Television \u2014 virtual display for agents").version(readCLIVersion()).option("-v", "Output the version number").showSuggestionAfterError(false).addHelpText("after", buildAgentHelpNote()).configureOutput({
55021
55060
  writeOut: (str) => env.stdout.write(str),
55022
55061
  writeErr: (str) => env.stderr.write(str),
55023
55062
  outputError: () => {
@@ -55041,11 +55080,21 @@ function createProgram(env, argv = []) {
55041
55080
  throw error48;
55042
55081
  }
55043
55082
  if (opts.persist) {
55083
+ if (opts.port === 0) {
55084
+ throw createDirectiveError(
55085
+ "tv serve --persist --port 0 requires a stable port; port 0 lets the operating system choose a runtime port and cannot produce a stable persisted-service startup URL. Set TELEVISION_PORT to a stable port or pass a non-zero --port."
55086
+ );
55087
+ }
55088
+ const clientPort = resolveClientPort(opts.port);
55044
55089
  const storagePath = import_node_path17.default.resolve(opts.storagePath ?? getTelevisionStoragePath());
55045
55090
  const profile2 = resolveACPAgentProfile(process.env);
55046
55091
  const daemonEnv = buildPersistedACPEnvironment(process.env, { developerHome: env.resolveHomeDir() });
55047
- if (process.env.TELEVISION_PORT !== void 0) daemonEnv.TELEVISION_PORT = process.env.TELEVISION_PORT;
55048
- if (process.env.TELEVISION_STORAGE_PATH !== void 0) daemonEnv.TELEVISION_STORAGE_PATH = process.env.TELEVISION_STORAGE_PATH;
55092
+ if (process.env.TELEVISION_PORT !== void 0 && process.env.TELEVISION_PORT !== "") {
55093
+ daemonEnv.TELEVISION_PORT = process.env.TELEVISION_PORT;
55094
+ }
55095
+ if (process.env.TELEVISION_STORAGE_PATH !== void 0 && process.env.TELEVISION_STORAGE_PATH !== "") {
55096
+ daemonEnv.TELEVISION_STORAGE_PATH = process.env.TELEVISION_STORAGE_PATH;
55097
+ }
55049
55098
  daemonEnv[TELEMETRY_LAUNCH_MODE_ENV] = "daemon";
55050
55099
  if (profile2 && !isACPCommandResolvable(profile2.command, daemonEnv)) {
55051
55100
  const error48 = createDirectiveError(
@@ -55086,14 +55135,14 @@ function createProgram(env, argv = []) {
55086
55135
  });
55087
55136
  throw error48;
55088
55137
  }
55089
- const port = resolveClientPort(opts.port);
55090
- const serverURLs2 = resolveBindAddresses(opts.listen).map((address) => buildServerURL(address, port));
55138
+ const serverURLs2 = resolveBindAddresses(opts.listen).map((address) => buildServerURL(address, clientPort));
55091
55139
  writeConnectURLs(env.stdout, serverURLs2, {
55092
55140
  installed: true,
55093
55141
  token: auth === true ? readOrCreateAuthToken(storagePath) : null
55094
55142
  });
55095
55143
  return;
55096
55144
  }
55145
+ warnForExplicitPortZero(opts.port);
55097
55146
  const profile = resolveACPAgentProfile(process.env);
55098
55147
  if (profile && !isACPCommandResolvable(profile.command, process.env)) {
55099
55148
  const error48 = createDirectiveError(
@@ -55163,10 +55212,11 @@ function createProgram(env, argv = []) {
55163
55212
  "Create a URL artifact that points at an absolute http(s) URL. Television records the pointer only and does not own or modify the remote page."
55164
55213
  ).requiredOption("--screen <id>", "Target screen ID").requiredOption("--title <title>", "Artifact title").requiredOption("--url <url>", "http(s) URL").option("--focus-artifact", "Focus the new artifact after creation").option("--no-focus", "Create the artifact in the background without changing focus").option("--port <number>", "Server port", parsePortOption).option("--storage-path <path>", "Directory containing the Television token").addHelpText("after", buildArtifactWorkflowHelpNote(true)).action(async (opts) => {
55165
55214
  const shouldFocus = resolveFocusDirective(argv, "create-url-artifact", "--focus-artifact");
55215
+ const artifactURL = opts.url.trim();
55166
55216
  const client = createAuthenticatedClient(opts);
55167
55217
  const { artifact } = await client.artifacts.create({
55168
55218
  kind: "url",
55169
- url: opts.url,
55219
+ url: artifactURL,
55170
55220
  title: opts.title,
55171
55221
  screenID: opts.screen
55172
55222
  });
@@ -55174,7 +55224,7 @@ function createProgram(env, argv = []) {
55174
55224
  await client.display.focus({ artifactID: artifact.id });
55175
55225
  }
55176
55226
  writeLine(env.stdout, `URL artifact ${artifact.id} created.`);
55177
- writeLine(env.stdout, `Television registered ${opts.url}.`);
55227
+ writeLine(env.stdout, `Television registered ${artifactURL}.`);
55178
55228
  });
55179
55229
  program2.command("storage-path").description("Print the Television storage path").action(() => {
55180
55230
  writeJSON(env.stdout, { storagePath: getTelevisionStoragePath() });
@@ -55290,7 +55340,7 @@ function createProgram(env, argv = []) {
55290
55340
  "Examples: ~/.openclaw/skills, ~/.hermes/skills, ~/.agents/skills.",
55291
55341
  "`tv skills install -i` runs the external skills installer against Television's bundled skills root."
55292
55342
  ].join("\n"));
55293
- skillsCommand.command("install").description("Copy bundled Television skills into an agent harness skills folder, or run the external installer against the bundled skills root").argument("[path]", "Destination agent skills folder (for example: ~/.openclaw/skills, ~/.hermes/skills, ~/.agents/skills)").option("-i, --interactive", "Run the external skills installer against the bundled Television skills root").option("--installed-by-agent <agent-runtime-harness-name>", "Agent runtime harness name performing this install").allowUnknownOption(true).action(async function(inputPath, opts) {
55343
+ skillsCommand.command("install").description("Copy bundled Television skills into an agent harness skills folder, or run the external installer against the bundled skills root").argument("[path]", "Destination agent skills folder (for example: ~/.openclaw/skills, ~/.hermes/skills, ~/.agents/skills)").option("-i, --interactive", "Run the external skills installer against the bundled Television skills root").option("--installed-by-agent <agent-runtime-harness-name>", "Agent runtime harness name performing this install").action(async function(inputPath, opts) {
55294
55344
  const bundledTelevisionSkillsCollectionRoot = env.resolveBundledSkillsRoot();
55295
55345
  if (opts.interactive) {
55296
55346
  if (inputPath) {
@@ -55373,6 +55423,10 @@ function listVisibleCLICommandNames() {
55373
55423
  async function runCLI(argv, environment = {}) {
55374
55424
  const env = createEnvironment(environment);
55375
55425
  try {
55426
+ if (argv.length === 1 && argv[0] === "-v") {
55427
+ writeLine(env.stdout, readCLIVersion());
55428
+ return 0;
55429
+ }
55376
55430
  const program2 = createProgram(env, argv);
55377
55431
  if (argv.length === 0) {
55378
55432
  program2.outputHelp();
@@ -55405,6 +55459,7 @@ if (!isVitestRuntime()) {
55405
55459
  }
55406
55460
  // Annotate the CommonJS export names for ESM import in node:
55407
55461
  0 && (module.exports = {
55462
+ PORT_ZERO_WARNING,
55408
55463
  inspectTelemetryBuildConfig,
55409
55464
  listVisibleCLICommandNames,
55410
55465
  resolveBundledSkillsRoot,
@@ -0,0 +1,36 @@
1
+ TELEVISION THIRD-PARTY LICENSING NOTICES
2
+
3
+ This file contains the license terms and attribution notices for third-party software and materials included in Television.
4
+ ================================================================================
5
+ lit-html@3.3.2
6
+ Licensed under BSD-3-Clause.
7
+ --------------------------------------------------------------------------------
8
+ BSD 3-Clause License
9
+
10
+ Copyright (c) 2017 Google LLC. All rights reserved.
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions are met:
14
+
15
+ 1. Redistributions of source code must retain the above copyright notice, this
16
+ list of conditions and the following disclaimer.
17
+
18
+ 2. Redistributions in binary form must reproduce the above copyright notice,
19
+ this list of conditions and the following disclaimer in the documentation
20
+ and/or other materials provided with the distribution.
21
+
22
+ 3. Neither the name of the copyright holder nor the names of its
23
+ contributors may be used to endorse or promote products derived from
24
+ this software without specific prior written permission.
25
+
26
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+